package com.itlong.cloud.controller.user;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.type.TypeReference;
import com.itlong.cloud.POJO.DTO.BaseDTO;
import com.itlong.cloud.POJO.DTO.app.AppFaceRecognitionDeviceAuthDTO;
import com.itlong.cloud.POJO.DTO.common.Message;
import com.itlong.cloud.POJO.DTO.common.PadFaceSyncDataDTO;
import com.itlong.cloud.POJO.DTO.operate.OperateCreateBaiduFaceDTO;
import com.itlong.cloud.POJO.DTO.property.*;
import com.itlong.cloud.POJO.DTO.sdk.CloudFaceApiDTO;
import com.itlong.cloud.POJO.DTO.smartcard.SmartCardUserUpdateDTO;
import com.itlong.cloud.POJO.PO.*;
import com.itlong.cloud.POJO.VO.MessageVO;
import com.itlong.cloud.POJO.VO.app.AppCreateBaiduFaceVO;
import com.itlong.cloud.POJO.VO.app.AppUserFaceVO;
import com.itlong.cloud.POJO.VO.operate.OperateFaceApplyInfoVO;
import com.itlong.cloud.POJO.VO.property.*;
import com.itlong.cloud.PlatformConstants;
import com.itlong.cloud.abstracts.BaseController;
import com.itlong.cloud.annotation.AuthAccessRequired;
import com.itlong.cloud.annotation.LoggerInfo;
import com.itlong.cloud.annotation.UnAuthAccessRequired;
import com.itlong.cloud.annotation.UnParamEncrypt;
import com.itlong.cloud.constants.LogDescConstant;
import com.itlong.cloud.constants.RedisConstant;
import com.itlong.cloud.enumerate.*;
import com.itlong.cloud.enumerate.ecode.AppErrorCodeEnum;
import com.itlong.cloud.enumerate.ecode.BaseErrorCodeEnum;
import com.itlong.cloud.enumerate.ecode.ErrorCode;
import com.itlong.cloud.enumerate.ecode.PropertyErrorCodeEnum;
import com.itlong.cloud.equip.property.IPadFaceSyncDataServiceClient;
import com.itlong.cloud.equip.property.IPropertyDeviceAuthServiceClient;
import com.itlong.cloud.equip.property.IPropertyEquipServiceClient;
import com.itlong.cloud.iottp.IIotBaiduFaceServiceClient;
import com.itlong.cloud.iottp.IIotTpJPushClientServiceClient;
import com.itlong.cloud.iottp.IIotVisitorFaceServiceClient;
import com.itlong.cloud.noncore.commons.IUserMovePushMessageServiceClient;
import com.itlong.cloud.project.app.IAppProjectServiceClient;
import com.itlong.cloud.project.operate.IOperateFaceApplyServiceClient;
import com.itlong.cloud.project.operate.IOperateProjectServiceClient;
import com.itlong.cloud.project.property.*;
import com.itlong.cloud.service.RedisService;
import com.itlong.cloud.thrown.DataAccessException;
import com.itlong.cloud.user.app.IAppMineServiceClient;
import com.itlong.cloud.user.property.IPropertyHouseHoldDeviceAuthServiceClient;
import com.itlong.cloud.user.property.IPropertyHouseHoldInfoServiceClient;
import com.itlong.cloud.user.property.IPropertyHouseholdRoleServiceClient;
import com.itlong.cloud.utils.encrypt.UserTokenUtil;
import com.itlong.cloud.utils.file.UploadFileUtil;
import com.itlong.cloud.utils.network.http.HttpProtocolUtil;
import com.itlong.cloud.utils.node.JsonUtil;
import com.itlong.cloud.utils.page.Page;
import com.itlong.cloud.utils.random.LogicIdUtil;
import com.itlong.cloud.utils.string.StringUtil;
import com.itlong.cloud.utils.words.StringHandlerUtil;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import sun.misc.BASE64Decoder;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.URI;
import java.text.NumberFormat;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * <desc>
 * 物业系统App用户信息聚合Controller。
 * </desc>
 *
 * @createDate 2017/08/29
 */
@RestController
@RequestMapping(path = "/setting/appuser")
@RefreshScope
public class PropertyHouseHoldInfoController extends BaseController {

    private static Logger LOG = LoggerFactory.getLogger(PropertyHouseHoldInfoController.class);
    private ExecutorService cachedThreadPool; //线程池
    @Value("${" + PlatformConstants.FILE_FTP_HOST + "}")
    public String FILE_FTP_HOST;
    @Value("${" + PlatformConstants.FILE_FTP_PORT + "}")
    public String FILE_FTP_PORT;
    @Value("${" + PlatformConstants.FILE_FTP_USERNAME + "}")
    public String FILE_FTP_USERNAME;
    @Value("${" + PlatformConstants.FILE_FTP_PASSWORD + "}")
    public String FILE_FTP_PASSWORD;
    @Value("${" + PlatformConstants.FILE_ACCESS_URL + "}")
    public String FILE_ACCESS_URL;

    public static Map<String, Object> project = new HashMap<>();
    //App用户信息服务接口协议提供对象
    @Autowired
    IPropertyHouseHoldInfoServiceClient iPropertyHouseHoldInfoServiceClient;

    //住户设备权限接口协议提供对象
    @Autowired
    IPropertyHouseHoldDeviceAuthServiceClient iPropertyHouseHoldDeviceAuthServiceClient;

    //设备服务接口
    @Autowired
    IPropertyEquipServiceClient iPropertyEquipServiceClient;

    //设备权限接口服务
    @Autowired
    IPropertyDeviceAuthServiceClient iPropertyDeviceAuthServiceClient;

    //项目信息接口服务
    @Autowired
    IOperateProjectServiceClient iOperateProjectServiceClient;

    //房屋信息服务接口协议提供对象.
    @Autowired
    IPropertyRoomInfoServiceClient iPropertyRoomInfoServiceClient;

    //楼栋信息服务接口协议提供对象.
    @Autowired
    IPropertyBuildInfoServiceClient iPropertyBuildInfoServiceClient;

    @Autowired
    IPropertyUnitInfoServiceClient iPropertyUnitInfoServiceClient;

    @Autowired
    IIotTpJPushClientServiceClient iIotTpJPushClientServiceClient;

    @Autowired
    IOperateFaceApplyServiceClient iOperateFaceApplyServiceClient;

    @Autowired
    IIotBaiduFaceServiceClient iIotBaiduFaceServiceClient;

    @Autowired
    IAppMineServiceClient iAppMineServiceClient;

    @Autowired
    IPropertyAccountServiceClient iPropertyAccountServiceClient;

    @Autowired
    IPadFaceSyncDataServiceClient iPadFaceSyncDataServiceClient;

    @Autowired
    IPropertyPaymentManageServiceClient iPropertyPaymentManageServiceClient;

    @Autowired
    IPropertyHouseholdRoleServiceClient iPropertyHouseholdRoleServiceClient;

    @Autowired
    IUserMovePushMessageServiceClient iUserMovePushMessageServiceClient;

    @Autowired
    IAppProjectServiceClient iAppProjectServiceClient;

    @Autowired
    IIotVisitorFaceServiceClient iIotVisitorFaceServiceClient;

    @Value("${" + PlatformConstants.PROPERTY_USER_TOKEN_KEY + "}")
    String userTokenKey;

    @Autowired
    RedisService redisService;

    @PostConstruct
    public void init() {
        cachedThreadPool = Executors.newFixedThreadPool(10);
    }

    /**
     * <desc>
     * 导入住户信息模板
     * </desc>
     *
     * @return MessageVO 标准格式化响应结果
     * @author Jiaqi.X
     * @createDate 2018/08/22
     */
    @ResponseBody
    @RequestMapping(path = "/exportUserModel", method = RequestMethod.POST)
    public Object getMeterInfoExcelTemplate() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String projectId = request.getAttribute("projectId") == null ? null : request.getAttribute("projectId").toString();
        MessageVO messageVO;
        try {
            //获取项目配置
            String projectType = iOperateProjectServiceClient.getProjectType(projectId);
            String templateFilePath;
            if (projectType.equals("1")) {
                templateFilePath = FILE_ACCESS_URL + FileCatalogEnum.PROJECT_STATIC_FILE.getType()
                        + PlatformConstants.APP_USER_INFO_House_FILE_NAME;
            } else {
                templateFilePath = FILE_ACCESS_URL + FileCatalogEnum.PROJECT_STATIC_FILE.getType()
                        + PlatformConstants.APP_USER_INFO_OFFICE_FILE_NAME;
            }
            URI excelTemplateDownLoadUrl = new URI(templateFilePath);
            messageVO = new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), (Object) excelTemplateDownLoadUrl.toString());
        } catch (Exception e) {
            throw new DataAccessException("【物业_住户管理_导出住户模板】导出住户模板失败", e);
        }
        return messageVO;
    }

    /**
     * <desc>
     * 添加App用户信息前判断用户是否存在
     * <desc/>
     *
     * @param appUserExistStatusDTO App用户存在状态数据传输对象
     * @return MessageVO 标准格式化响应结果
     * @author zhangs
     * @createDate 2017/09/26
     */
    @RequestMapping(path = "/manage/getAppUserExistStatus", method = RequestMethod.POST)
    @ResponseBody
    public Object getAppUserExistStatus(AppUserExistStatusDTO appUserExistStatusDTO) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            appUserExistStatusDTO = HttpProtocolUtil.parseRequestParamToDTO(AppUserExistStatusDTO.class, request);
            if (appUserExistStatusDTO == null) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            String projectId = appUserExistStatusDTO.getProjectId();
            String phoneNum = appUserExistStatusDTO.getPhoneNum();
            //判断参数合法性
            if (StringUtils.isBlank(projectId)) {
                return new MessageVO(PropertyErrorCodeEnum.PUB_PROJECT_ID_EMPTY_ERR.getErrorCode());
            }
            //手机号合法性判断
            if (StringUtils.isBlank(phoneNum)) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_PHONENUM_NOT_NULL.getErrorCode());
            }
            //查询App用户是否存在
            Integer result = iPropertyHouseHoldInfoServiceClient.getAppUserExistStatus(projectId, phoneNum);
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), result);
        } catch (Exception e) {
            throw new DataAccessException(String.format("【物业系统_住户信息管理_判断住户是否已存在】" +
                    " 判断住户是否存在失败"), e);
        }
    }

    /**
     * <desc>
     * 对导入文件的文件格式等基本信息进行合法性初步检测
     * </desc>
     *
     * @param workbook        Excel操作对象
     * @param availableSheets 合法可用到Sheet页
     * @return MessageVO 标准格式化响应结果
     * @author Jiaqi.X
     * @createDate 2018/08/17
     */
    private MessageVO checkImportUserInfoFileValid(HSSFWorkbook workbook, List<HSSFSheet> availableSheets, String[] titles) {
        //获取Excel的Sheet页面数，每个Excel文件至少会有一个Sheet页(Excel文件本身到限定)
        int sheetCount = workbook.getNumberOfSheets();
//        int totalRowsCount = 0;
        //遍历当前文件的所有Sheet页，进行合法性检测
        for (int sheetIndex = 0; sheetIndex < sheetCount; sheetIndex++) {
            HSSFSheet oneSheet = workbook.getSheetAt(sheetIndex);
            int rowsCountOfCurrentSheet = oneSheet.getPhysicalNumberOfRows();
//            totalRowsCount += rowsCountOfCurrentSheet;
            if (rowsCountOfCurrentSheet < 1) {
                continue;
            }
            //对当前Sheet的列数量进行合法性判断
            HSSFRow headerRow = oneSheet.getRow(0);
            int columnCount = oneSheet.getRow(0).getPhysicalNumberOfCells();
            if (columnCount != titles.length) {
                return new MessageVO(PropertyErrorCodeEnum.PROPERTY_FEE_EXCEL_COLUMN_COUNT_MISMATCH_ERR.getErrorCode());
            }
            //每个Sheet页的第一页为列标题，进行标题头名称进行合法性判断
            DataFormatter dataFormatter = new DataFormatter();
            for (int columnIndex = 0; columnIndex < columnCount; columnIndex++) {
                String oneFieldValue = dataFormatter.formatCellValue(headerRow.getCell(columnIndex));

                String columnTitle = titles[columnIndex];
                if (!StringHandlerUtil.compareStrWithOutEmpty(oneFieldValue, columnTitle)) {
                    ErrorCode errorCode = PropertyErrorCodeEnum.PROPERTY_FEE_EXCEL_COLUMN_TITLE_MISMATCH_ERR.getErrorCode();
                    return new MessageVO(errorCode,
                            String.format(errorCode.getCodeMsg(), oneFieldValue, columnTitle));
                }
            }
            //至少有一行实际数据可导入才加入Sheet处理列表
            if (rowsCountOfCurrentSheet > 1) {
                availableSheets.add(oneSheet);
            }
        }
        //没有数据
        if (availableSheets.isEmpty()) {
            return new MessageVO(PropertyErrorCodeEnum.PROJECT_IMPORT_FILE_NO_DATA_ERR.getErrorCode());
        }
        return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode());
    }

    /**
     * <desc>
     * 从可用的Sheet页中解析车位信息
     * </desc>
     *
     * @param availableSheets 合法可用到Sheet页
     * @return 错误的车位信息及其错误原因
     * @author Jiaqi.X
     * @createDate 2018/08/30
     */
    private List<PropertyHouseHoldInfoRowDTO> getImportUserInfoFromFile(String token, Integer count, Integer percent, ProjectPO projectPO, List<AppUserGetUserInfoDTO> addUsers,
                                                                        List<AppUserUpdateUserRoomStatusDTO> moveUsers,
                                                                        List<HSSFSheet> availableSheets, String projectId, String loginUserId) throws Exception {
        // Excel单元格数据操作对象
        DataFormatter dataFormatter = new DataFormatter();
        // 错误的行信息列表
        List<PropertyHouseHoldInfoRowDTO> errorImportDataList = new ArrayList<>();
        //遍历所有可用Sheet，逐行处理每个Sheet的数据
        Set<String> repeat = new HashSet<>();
        Map<String, Integer> roomMax = new HashMap<>();
        NumberFormat numberFormat = NumberFormat.getInstance();
        // 设置精确到小数点后2位
        numberFormat.setMaximumFractionDigits(2);
        for (HSSFSheet oneSheet : availableSheets) {
            int rowsCountOfCurrentSheet = oneSheet.getPhysicalNumberOfRows();
            for (int rowIndex = 1; rowIndex < rowsCountOfCurrentSheet; rowIndex++) {
                percent++;
                project.put(projectId, numberFormat.format((float) (rowIndex - 1) / (float) count * 100));
                redisService.set(RedisConstant.PROPERTY_USER_MOVE_PERCENT_KEY + projectId, RedisConstant.PROPERTY_USER_MOVE_PERCENT_CACHE_TIME,
                        project.get(projectId).toString());
                if (percent <= 2) {
                    //触发推送
                    iUserMovePushMessageServiceClient.pushMessage(projectId, token);
                }
                HSSFRow row = oneSheet.getRow(rowIndex);
                if (row != null) {
                    //对当前Sheet中的当前行进行数据处理
                    PropertyHouseHoldInfoRowDTO propertyPropertyFeeRowDTO = handleOneRowAddressInfo(roomMax, repeat, projectPO, row, addUsers, moveUsers, dataFormatter, projectId, loginUserId);
                    //若存在错误信息，则将加入错误列表
                    if (propertyPropertyFeeRowDTO != null && !propertyPropertyFeeRowDTO.getErrorCodes().isEmpty()) {
                        this.addErrorPropertyFeeInfoToList(errorImportDataList, propertyPropertyFeeRowDTO);
                    }
                }
            }
        }
        return errorImportDataList;
    }

    /**
     * <desc>
     * 向错误列表中增加有错误的物业费信息
     * </desc>
     *
     * @param errorImportDataList   错误列表
     * @param propertyParkingRowDTO 有错误的车位信息
     * @author Jiaqi.X
     * @createDate 2018/08/17
     */
    private void addErrorPropertyFeeInfoToList(List<PropertyHouseHoldInfoRowDTO> errorImportDataList, PropertyHouseHoldInfoRowDTO propertyParkingRowDTO) {
        for (PropertyHouseHoldInfoRowDTO oneAddressInfo : errorImportDataList) {
            if ((oneAddressInfo.getRowNum() == propertyParkingRowDTO.getRowNum())
                    && (StringHandlerUtil.compareStrWithOutEmpty(oneAddressInfo.getSheetName(), propertyParkingRowDTO.getSheetName()))) {
                return;
            }
        }
        errorImportDataList.add(propertyParkingRowDTO);
    }

    /**
     * <desc>
     * 根据Excel的一行数据获取单条"物业费信息及其错误码列表".
     * </desc>
     *
     * @param hssfRow       Excel的一行数据
     * @param dataFormatter Excel单元格数据的读取器
     * @return 错误码列表
     * @author Jiaqi.X
     * @createDate 2018/08/30
     */
    private PropertyHouseHoldInfoRowDTO handleOneRowAddressInfo(Map<String, Integer> roomMax, Set<String> repeatSet, ProjectPO projectPO, HSSFRow hssfRow, List<AppUserGetUserInfoDTO> addUsers,
                                                                List<AppUserUpdateUserRoomStatusDTO> moveUsers,
                                                                DataFormatter dataFormatter, String projectId, String loginUserId) throws Exception {
        PropertyHouseHoldInfoRowDTO propertyHouseHoldInfoRowDTO = new PropertyHouseHoldInfoRowDTO();
        List<ErrorCode> errorCodes = propertyHouseHoldInfoRowDTO.getErrorCodes();
        //首先登记所属的Sheet名称和行号
        propertyHouseHoldInfoRowDTO.setSheetName(hssfRow.getSheet().getSheetName());
        propertyHouseHoldInfoRowDTO.setRowNum(hssfRow.getRowNum() + 1);
        if (StringUtils.isBlank(dataFormatter.formatCellValue(hssfRow.getCell(0))) &&
                StringUtils.isBlank(dataFormatter.formatCellValue(hssfRow.getCell(1))) &&
                StringUtils.isBlank(dataFormatter.formatCellValue(hssfRow.getCell(2)))
        ) {
            return null;
        }
        // 处理手机号
        String phone = dataFormatter.formatCellValue(hssfRow.getCell(1));
        propertyHouseHoldInfoRowDTO.setPhone(phone);
        // 处理地址
        String address = dataFormatter.formatCellValue(hssfRow.getCell(2));
        propertyHouseHoldInfoRowDTO.setAddress(address);
        //姓名
        String realName = dataFormatter.formatCellValue(hssfRow.getCell(0));
        propertyHouseHoldInfoRowDTO.setRealName(realName);
        //身份
        String houseTypeStr = dataFormatter.formatCellValue(hssfRow.getCell(4));
        propertyHouseHoldInfoRowDTO.setHouseType(houseTypeStr);
        //处理用户分组
        String userGroup = dataFormatter.formatCellValue(hssfRow.getCell(3));
        propertyHouseHoldInfoRowDTO.setUserGroup(userGroup);

        if (!phone.matches("^[1][3,4,5,6,7,8,9][0-9]{9}$")) {
            errorCodes.add(PropertyErrorCodeEnum.APPUSER_PHONENUM_ERR.getErrorCode());
            return propertyHouseHoldInfoRowDTO;
        }
        if (StringUtils.isBlank(address)) {
            errorCodes.add(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            return propertyHouseHoldInfoRowDTO;
        }
        if (StringUtils.isBlank(realName)) {
            errorCodes.add(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            return propertyHouseHoldInfoRowDTO;
        }
        if (!realName.matches("^[a-zA-Z0-9\\u4E00-\\u9FA5]+$")) {
            errorCodes.add(PropertyErrorCodeEnum.PROPERTY_IMPORT_NAME_ERROR.getErrorCode());
            return propertyHouseHoldInfoRowDTO;
        }
        if (realName.length() > 15) {
            errorCodes.add(PropertyErrorCodeEnum.PROPERTY_REAL_NAME_LENGTH_ERROR.getErrorCode());
            return propertyHouseHoldInfoRowDTO;
        }

        //将用户分组中的中文逗号替换为英文逗号
        userGroup.replaceAll("，", ",");
        //查看用户输入的分组名称中是否有不存在的分组
        List<String> userGroupList = new ArrayList<>();
        if (StringUtils.isNotBlank(userGroup)) {
            userGroupList = iPropertyHouseholdRoleServiceClient.checkUserGroupExist(userGroup, projectId);

            if (userGroupList.isEmpty() || userGroupList.size() != StringHandlerUtil.splitStringList(userGroup).size()) {
                errorCodes.add(PropertyErrorCodeEnum.PROPERTY_HOUSEHOLD_ROLE_NAME_NOT_EXIST_ERR.getErrorCode());
                return propertyHouseHoldInfoRowDTO;
            }
        }
        //判断用户身份是否存在
        Integer houseType = iPropertyHouseHoldInfoServiceClient.getUserTypeIdByName(houseTypeStr, projectId);
        if (houseType == null) {
            errorCodes.add(PropertyErrorCodeEnum.PROPERTY_USER_IDENTITY_LENGTH_ERROR.getErrorCode());
            return propertyHouseHoldInfoRowDTO;
        }

        address.replaceAll(" ", "");
        if (!address.matches(".*-.*-.*")) {
            errorCodes.add(PropertyErrorCodeEnum.PROPERTY_PAYMEN_ADDRESS_ERROR.getErrorCode());
            return propertyHouseHoldInfoRowDTO;
        }
        Map<String, Object> map = iPropertyHouseHoldInfoServiceClient.getRoomInfoByBuildNameAndUnitNameAndRoomNum(address, projectId);
        if (map == null) {
            errorCodes.add(PropertyErrorCodeEnum.ROOM_IS_NOT_EXISTS.getErrorCode());
            return propertyHouseHoldInfoRowDTO;
        }
        //判断用户在当前项目有没有房间
        Map<String, Object> room = iPropertyHouseHoldInfoServiceClient.checkUserInProject(phone, projectId, map.get("roomId").toString());
        //当前房间中的住户数量
        Integer currentExistCount;
        if (roomMax.get(map.get("roomId").toString()) == null) {
            currentExistCount = iPropertyHouseHoldInfoServiceClient.getMoveInHouseHoldCount(map.get("roomId").toString(), projectId);
        } else {
            currentExistCount = roomMax.get(map.get("roomId").toString());
        }
        //获取该房屋类型 1住宅 2办公
        Integer housesType = iPropertyHouseHoldInfoServiceClient.getHousesType(map.get("roomId").toString(), projectId);
        //住宅最大授权数，最大为10
        Integer authMaxNum = projectPO.getAuthMaxNum();
        //办公最大授权数，最大为500
        Integer officeAuthMaxNum = projectPO.getOfficeAuthMaxNum();
        if(officeAuthMaxNum == 0){
            //当productType为2 且officeAuthMaxNum为0时，前端默认展示授权11人
            officeAuthMaxNum = 11;
        }
        String projectType = projectPO.getProjectType();

        //已达到或超过项目中最大授权人数则无法添加住户
        if ("1".equals(projectType) && currentExistCount >= authMaxNum) {
            errorCodes.add(PropertyErrorCodeEnum.APPUSER_AUTHMAXNUM_FILL.getErrorCode());
            return propertyHouseHoldInfoRowDTO;
        }
        if ("2".equals(projectType) && currentExistCount >= officeAuthMaxNum) {
            errorCodes.add(PropertyErrorCodeEnum.APPUSER_AUTHMAXNUM_FILL.getErrorCode());
            return propertyHouseHoldInfoRowDTO;
        }

        address.replaceAll(" ", "");
        if (!address.matches(".*-.*-.*")) {
            errorCodes.add(PropertyErrorCodeEnum.PROPERTY_PAYMEN_ADDRESS_ERROR.getErrorCode());
            return propertyHouseHoldInfoRowDTO;
        }

        //查询房间是否存在及是否有业主
        Integer check = iPropertyPaymentManageServiceClient.checkRoomExists(address, projectId);
        if (check == 1) {
            errorCodes.add(PropertyErrorCodeEnum.ROOM_IS_NOT_EXISTS.getErrorCode());
            return propertyHouseHoldInfoRowDTO;
        }
        if (!repeatSet.add(phone + address)) {
            errorCodes.add(PropertyErrorCodeEnum.PROPERTY_REPEAT_REMOVE_ERROR.getErrorCode());
            return propertyHouseHoldInfoRowDTO;
        }
        if (houseType==1) {
            if (!repeatSet.add(address + houseType)) {
                errorCodes.add(PropertyErrorCodeEnum.PROPERTY_REPEAT_OWNER_USER_REMOVE_ERROR.getErrorCode());
                return propertyHouseHoldInfoRowDTO;
            }
        }
        //组装对象
        String userId = room != null ? StringHandlerUtil.getNullOrStringForObject(room.get("userId")) : null;
        Boolean roomExists = room != null ? room.get("roomExists") != null ? (Boolean) room.get("roomExists") : null : null;
        if (roomExists != null && roomExists) {
            errorCodes.add(PropertyErrorCodeEnum.PROPERTY_REPEAT_USER_REMOVE_ERROR.getErrorCode());
            return propertyHouseHoldInfoRowDTO;
        }
        if (StringUtils.isBlank(userId)) {
            Optional<AppUserGetUserInfoDTO> optional = addUsers.stream().filter(user -> user.getPhoneNum().equals(phone)).findFirst();
            if (!optional.isPresent()) {
                AppUserGetUserInfoDTO appUserGetUserInfoDTO = new AppUserGetUserInfoDTO();
                appUserGetUserInfoDTO.setRealName(realName);
                appUserGetUserInfoDTO.setProjectId(projectId);
                appUserGetUserInfoDTO.setLoginUserId(loginUserId);
                appUserGetUserInfoDTO.setPhoneNum(phone);
                appUserGetUserInfoDTO.setRoleIdList(userGroupList);
                List<AppUserRoomDTO> appUserRoomDTOS = new ArrayList<>();
                AppUserRoomDTO dto = new AppUserRoomDTO();
                dto.setHouserType(houseType);
                dto.setBuildId(map.get("buildId").toString());
                dto.setUnitId(map.get("unitId").toString());
                dto.setRoomId(map.get("roomId").toString());
                dto.setRoomNum(map.get("roomNum").toString());
                appUserRoomDTOS.add(dto);
                if(housesType==1) {
                    Map<String, String> resultMap = this.checkOwnerExist(appUserRoomDTOS, null);
                    String isExist = resultMap.get("isExist");
                    if (StringHandlerUtil.compareStrIgnoreCaseWithOutEmpty("true", isExist)) {
                        errorCodes.add(PropertyErrorCodeEnum.PROPERTY_OWNER_EXISTS__ERROR.getErrorCode());
                        return propertyHouseHoldInfoRowDTO;
                    }
                }
                appUserGetUserInfoDTO.setAppUserRoomDTOS(appUserRoomDTOS);
                addUsers.add(appUserGetUserInfoDTO);
            }else{
                AppUserGetUserInfoDTO appUserGetUserInfoDTO = optional.get();
                List<AppUserRoomDTO> appUserRoomDTOS = appUserGetUserInfoDTO.getAppUserRoomDTOS();
                AppUserRoomDTO dto = new AppUserRoomDTO();
                dto.setHouserType(houseType);
                dto.setBuildId(map.get("buildId").toString());
                dto.setUnitId(map.get("unitId").toString());
                dto.setRoomId(map.get("roomId").toString());
                dto.setRoomNum(map.get("roomNum").toString());
                appUserRoomDTOS.add(dto);
                if(housesType==1) {
                    Map<String, String> resultMap = this.checkOwnerExist(appUserRoomDTOS, null);
                    String isExist = resultMap.get("isExist");
                    if (StringHandlerUtil.compareStrIgnoreCaseWithOutEmpty("true", isExist)) {
                        errorCodes.add(PropertyErrorCodeEnum.PROPERTY_OWNER_EXISTS__ERROR.getErrorCode());
                        return propertyHouseHoldInfoRowDTO;
                    }
                }
                appUserGetUserInfoDTO.getRoleIdList().addAll(userGroupList);
                appUserGetUserInfoDTO.setAppUserRoomDTOS(appUserRoomDTOS);
            }
        }else{
            Optional<AppUserUpdateUserRoomStatusDTO> move = moveUsers.stream().filter(user -> user.getAppUsersRemoveDTOList().stream().filter(u ->
                    u.getUserId().equals(userId)).findFirst().isPresent()).findFirst();
            if (move.isPresent()) {
                AppUserUpdateUserRoomStatusDTO dto = move.get();
                List<AppUsersRemoveDTO> appUsersRemoveDTOList = dto.getAppUsersRemoveDTOList();
                AppUsersRemoveDTO removeDTO = appUsersRemoveDTOList.get(0);
                List<AppUserRoomDTO> appUserRoomDTOS = removeDTO.getAppUserRoomDTOS();   //App用户房间信息数据传输对象
                if (appUserRoomDTOS == null) {
                    appUserRoomDTOS = new ArrayList<>();
                    removeDTO.setAppUserRoomDTOS(appUserRoomDTOS);
                }
                AppUserRoomDTO roomDTO = new AppUserRoomDTO();
                roomDTO.setBuildId(map.get("buildId").toString());
                roomDTO.setUnitId(map.get("unitId").toString());
                roomDTO.setRoomId(map.get("roomId").toString());
                roomDTO.setRoomNum(map.get("roomNum").toString());
                roomDTO.setHouserType(houseType);
                if(houseType==1) {
                    Map<String, String> resultMap = this.checkOwnerExist(appUserRoomDTOS, userId);
                    String isExist = resultMap.get("isExist");
                    if (StringHandlerUtil.compareStrIgnoreCaseWithOutEmpty("true", isExist)) {
                        errorCodes.add(PropertyErrorCodeEnum.PROPERTY_OWNER_EXISTS__ERROR.getErrorCode());
                        return propertyHouseHoldInfoRowDTO;
                    }
                }
                dto.getRoleIdList().addAll(userGroupList);
                appUserRoomDTOS.add(roomDTO);
            } else {
                AppUserUpdateUserRoomStatusDTO dto = new AppUserUpdateUserRoomStatusDTO();
                List<AppUsersRemoveDTO> appUsersRemoveDTOList = new ArrayList<>();
                dto.setRoleIdList(userGroupList);
                dto.setAppUsersRemoveDTOList(appUsersRemoveDTOList);
                AppUsersRemoveDTO removeDTO = new AppUsersRemoveDTO();
                appUsersRemoveDTOList.add(removeDTO);
                removeDTO.setUserId(userId);
                removeDTO.setProjectId(projectId);
                removeDTO.setLoginUserId(loginUserId);
                removeDTO.setUserRoomStatus(2);
                List<AppUserRoomDTO> appUserRoomDTOS = new ArrayList<>();  //App用户房间信息数据传输对象
                removeDTO.setAppUserRoomDTOS(appUserRoomDTOS);
                AppUserRoomDTO roomDTO = new AppUserRoomDTO();
                roomDTO.setBuildId(map.get("buildId").toString());
                roomDTO.setUnitId(map.get("unitId").toString());
                roomDTO.setRoomId(map.get("roomId").toString());
                roomDTO.setRoomNum(map.get("roomNum").toString());
                roomDTO.setHouserType(houseType);
                appUserRoomDTOS.add(roomDTO);
                if(houseType==1) {
                    Map<String, String> resultMap = this.checkOwnerExist(appUserRoomDTOS, userId);
                    String isExist = resultMap.get("isExist");
                    if (StringHandlerUtil.compareStrIgnoreCaseWithOutEmpty("true", isExist)) {
                        errorCodes.add(PropertyErrorCodeEnum.PROPERTY_OWNER_EXISTS__ERROR.getErrorCode());
                        return propertyHouseHoldInfoRowDTO;
                    }
                }
                dto.setRealName(realName);
                dto.setUserId(userId);
                moveUsers.add(dto);
            }
        }
        roomMax.put(map.get("roomId").toString(), ++currentExistCount);
        return propertyHouseHoldInfoRowDTO;
    }


    /**
     * <desc>
     * 检测当前项目是否有迁入状态
     * <desc/>
     *
     * @return MessageVO 标准格式化响应结果
     * @author zhangs
     * @createDate 2017/09/26
     */
    @RequestMapping(path = "/manage/checkBatchPercent", method = RequestMethod.POST)
    @ResponseBody
    public Object checkBatchPercent(HttpServletRequest request) {
        try {
            String projectId = request.getAttribute("projectId") == null ? null : request.getAttribute("projectId").toString();
            String token = request.getAttribute("token") == null ? null : request.getAttribute("token").toString();
            if (project.get(projectId) != null) {
                iUserMovePushMessageServiceClient.pushMessage(projectId, token);
            }
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode());
        } catch (Exception e) {
            throw new DataAccessException("【检测当前项目是否有迁入状态出错】", e);
        }
    }

    /**
     * <desc>
     * 获取迁出的错误结果
     * <desc/>
     *
     * @return MessageVO 标准格式化响应结果
     * @author zhangs
     * @createDate 2017/09/26
     */
    @RequestMapping(path = "/manage/getErrorList", method = RequestMethod.POST)
    @ResponseBody
    public Object getErrorList(HttpServletRequest request) {
        try {
            String projectId = request.getAttribute("projectId") == null ? null : request.getAttribute("projectId").toString();
            List<PropertyHouseHoldInfoRowDTO> errorImportDataList = redisService.get(RedisConstant.PROPERTY_USER_MOVE_ERRORLIST_KEY + projectId) != null ?
                    JsonUtil.decode(redisService.get(RedisConstant.PROPERTY_USER_MOVE_ERRORLIST_KEY + projectId), new TypeReference<List<PropertyHouseHoldInfoRowDTO>>() {
                    }) : new ArrayList<>();
            Map<String, Object> result = redisService.get(RedisConstant.PROPERTY_USER_MOVE_RESULT_KEY + projectId) != null ?
                    JsonUtil.toObject(redisService.get(RedisConstant.PROPERTY_USER_MOVE_RESULT_KEY + projectId), HashMap.class) : null;
            if (result != null) {
                result.put("errorList", errorImportDataList);
            }
            redisService.del(RedisConstant.PROPERTY_USER_MOVE_RESULT_KEY + projectId);
            redisService.del(RedisConstant.PROPERTY_USER_MOVE_ERRORLIST_KEY + projectId);
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), result);
        } catch (Exception e) {
            throw new DataAccessException("【检测当前项目是否有迁入状态出错】", e);
        }
    }

    /**
     * <desc>
     * 批量迁入用户
     * </desc>
     *
     * @return 标准格式化响应结果
     * @author Jiaqi.X
     * @createDate 2020/03/18
     */
    @ResponseBody
//    @AuthAccessRequired
    @PostMapping("/importUserInfo")
    @LoggerInfo(operateDesc = LogDescConstant.PARKING_EXPORT_LOG_DESC)
    public Object importUserInfo(BaseDTO baseDTO, HttpServletRequest httpServletRequest) {
        try {
            baseDTO = HttpProtocolUtil.parseRequestParamToDTO(BaseDTO.class, httpServletRequest);
            if (baseDTO == null) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            if (StringUtils.isBlank(baseDTO.getProjectId())) {
                return new MessageVO(PropertyErrorCodeEnum.PUB_PROJECT_ID_EMPTY_ERR.getErrorCode());
            }
            if (project.get(baseDTO.getProjectId()) != null) {
                return new MessageVO(PropertyErrorCodeEnum.PUB_PROJECT_BATCH_ERROR.getErrorCode());
            }
            String projectId = baseDTO.getProjectId();
            String loginUserId = baseDTO.getLoginUserId();
            String token = baseDTO.getToken();
            List<AppUserGetUserInfoDTO> addUsers = new ArrayList<>();
            List<AppUserUpdateUserRoomStatusDTO> moveUsers = new ArrayList<>();
            boolean isMultipart = ServletFileUpload.isMultipartContent(httpServletRequest);
            if (!isMultipart) {
                //是否是带文件上传的表单
                return new MessageVO(PropertyErrorCodeEnum.PROJECT_IMPORT_FILE_LOST_ERR.getErrorCode());
            }
            MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) httpServletRequest;
            Map<String, MultipartFile> fileList = multipartRequest.getFileMap();
            if (fileList.size() < 1) {
                return new MessageVO(PropertyErrorCodeEnum.PROJECT_IMPORT_FILE_LOST_ERR.getErrorCode());
            }
            if (fileList.size() > 1) {
                //目前仅支持一次处理单个文件
                return new MessageVO(PropertyErrorCodeEnum.PROJECT_EXCEL_FILE_TOO_MANY_ERR.getErrorCode());
            }
            List<HSSFSheet> availableSheets = new ArrayList<>(); //合法的Sheet页
            //获取Excel文件
            Map.Entry<String, MultipartFile> fileEntry = fileList.entrySet().iterator().next();
            MultipartFile excelFile = fileEntry.getValue();
            String excelFileName = excelFile.getOriginalFilename();
            // 获取上传文件的类型
            String excelContentType = StringHandlerUtil.copySubStr(excelFileName, excelFileName.lastIndexOf('.'), excelFileName.length());
            if (!(".xls".equalsIgnoreCase(excelContentType) || ".xlsx".equalsIgnoreCase(excelContentType))) {
                return new MessageVO(PropertyErrorCodeEnum.PROJECT_IMPORT_FILE_TYPE_ERR.getErrorCode());
            }
            //创建Excel操作对象，07之前版本(*.xls)使用HSSFWorkBook 07之后版本使用（*.xlsx）XSSFWorkbook
            HSSFWorkbook workbook;
            POIFSFileSystem fileSystem;
            try {
                fileSystem = new POIFSFileSystem(excelFile.getInputStream());
                workbook = new HSSFWorkbook(fileSystem);
            } catch (Exception e) {
                return new MessageVO(PropertyErrorCodeEnum.PROJECT_IMPORT_FILE_CONTENT_TYPE_ERR.getErrorCode());
            }
            cachedThreadPool.execute(() -> {
                MessageVO messageVO = new MessageVO();
                try {
                    project.put(projectId, 1);
                    Integer count = 0;
                    Integer percent = 1;
                    //查询当前项目信息
                    ProjectPO projectPO = iOperateProjectServiceClient.getOneProject(projectId);
                    List<PropertyHouseHoldInfoRowDTO> errorImportDataList;
                    try {
                        //对导入文件的数据格式等基本信息进行合法性初步检测
                        messageVO = this.checkImportUserInfoFileValid(workbook, availableSheets, PlatformConstants.PROPERTY_USER_EXCEL_COLUMN_TITLES);
                        if (!messageVO.getMsgCode().equals(BaseErrorCodeEnum.SUCCESS.getErrorCode().getMainCode())) {
//                                return messageVO;
                        }
                        //处理Excel文件中的物业费数据
                        count = availableSheets.get(0).getPhysicalNumberOfRows() - 1;
                        errorImportDataList = this.getImportUserInfoFromFile(token, count, percent, projectPO, addUsers, moveUsers, availableSheets, projectId, loginUserId);
                    } finally {
                        fileSystem.close();
                    }
                    //若有非法数据，返回非法数据
                    if (!errorImportDataList.isEmpty()) {
                        //保存非法数据
                        redisService.set(RedisConstant.PROPERTY_USER_MOVE_ERRORLIST_KEY + projectId, RedisConstant.PROPERTY_USER_MOVE_ERRORLIST_CACHE_TIME, errorImportDataList);
                    }
                    //保存成功和失败的用户数量
                    Map<String, Object> param = new HashMap<>();
                    param.put("errorNum", errorImportDataList.size());
                    param.put("successNum", addUsers.size() + moveUsers.size());
                    redisService.set(RedisConstant.PROPERTY_USER_MOVE_RESULT_KEY + projectId, RedisConstant.PROPERTY_USER_MOVE_RESULT_CACHE_TIME, param);
                    // 创建一个数值格式化对象
                    NumberFormat numberFormat = NumberFormat.getInstance();
                    // 设置精确到小数点后2位
                    numberFormat.setMaximumFractionDigits(2);
                    if (!addUsers.isEmpty() || !moveUsers.isEmpty()) {
                        count = count / 2 + addUsers.size() + moveUsers.size();
                        if (!addUsers.isEmpty()) {
                            //添加用户
                            for (AppUserGetUserInfoDTO addUser : addUsers) {
                                AppUserGetUserInfoDTO appUserGetUserInfoDTO;
                                appUserGetUserInfoDTO = addUser;
                                if (appUserGetUserInfoDTO.getIdCards() != null && !"".equals(appUserGetUserInfoDTO.getIdCards())) {
                                    appUserGetUserInfoDTO.setIdCards(UserTokenUtil.getPassword(appUserGetUserInfoDTO.getIdCards(), userTokenKey));
                                }
                                //是否使用云对讲： 0-否，1-是
                                Integer isSmartCommunity = projectPO.getIsSmartCommunity();
                                //用户房间信息不能为空
                                List<AppUserRoomDTO> appUserRoomDTOS = appUserGetUserInfoDTO.getAppUserRoomDTOS();
                                if ((appUserRoomDTOS == null) || (appUserRoomDTOS.size() == 0)) {
                                    continue;
                                }
                                //判断新加住户业主房间地址中是否已存在业主
                                //Map<String, value> ：isExist业主是否存在，roomNum 业主存在时的房间号,userId 业主userId
                                //保存用户信息
                                appUserGetUserInfoDTO.setProjectId(projectId);
                                appUserGetUserInfoDTO.setUserId(LogicIdUtil.userBusinessId());
                                iPropertyHouseHoldInfoServiceClient.addAppUser(appUserGetUserInfoDTO, isSmartCommunity, loginUserId);
                                percent++;

                                if (appUserGetUserInfoDTO.getRoleIdList() != null && !appUserGetUserInfoDTO.getRoleIdList().isEmpty()){
                                    //用户角色组授权
                                    //电梯授权
                                    //分组id去重
                                    AppUserInfoPO appUserInfoPO = iAppMineServiceClient.getUserInfoByPhoneNo(appUserGetUserInfoDTO.getPhoneNum());
                                    if (appUserInfoPO != null && StringUtils.isNotBlank(appUserInfoPO.getUserId())){
                                        appUserGetUserInfoDTO.setUserId(appUserInfoPO.getUserId());
                                    }
                                    List<String> oldRoleGroupIdList = iPropertyHouseHoldInfoServiceClient.getOldRoleGroupId(appUserGetUserInfoDTO.getUserId(), projectId);
                                    appUserGetUserInfoDTO.getRoleIdList().addAll(oldRoleGroupIdList);
                                    Set<String> roleIdSet = new HashSet<>(appUserGetUserInfoDTO.getRoleIdList());
                                    this.userDeviceAuth(new ArrayList<>(roleIdSet), projectId, appUserGetUserInfoDTO.getUserId(), loginUserId);
                                }


                                project.put(projectId, numberFormat.format((float) percent / (float) count * 100));
                                redisService.set(RedisConstant.PROPERTY_USER_MOVE_PERCENT_KEY + projectId, RedisConstant.PROPERTY_USER_MOVE_PERCENT_CACHE_TIME,
                                        project.get(projectId).toString());
                            }
                        }
                        if (!moveUsers.isEmpty()) {
                            for (AppUserUpdateUserRoomStatusDTO dto : moveUsers) {
                                AppUserUpdateUserRoomStatusDTO appUserUpdateUserRoomStatusDTO = dto;
                                appUserUpdateUserRoomStatusDTO.setProjectId(projectId);
                                CloudFaceApiDTO cloudFaceApiDTO = new CloudFaceApiDTO();
                                cloudFaceApiDTO.setRealName(appUserUpdateUserRoomStatusDTO.getRealName());
                                cloudFaceApiDTO.setUserId(appUserUpdateUserRoomStatusDTO.getUserId());
                                iPropertyHouseHoldInfoServiceClient.updateUserInfo(cloudFaceApiDTO);

                                List<AppUsersRemoveDTO> appUsersRemoveDTOS = appUserUpdateUserRoomStatusDTO.getAppUsersRemoveDTOList();
                                //是否启用云对讲，默认0,0-否，1-是
                                Integer isSmartCommunity = projectPO.getIsSmartCommunity();
                                //判断迁入住户业主房间地址中是否已存在业主
                                for (AppUsersRemoveDTO appUsersRemoveDTO : appUsersRemoveDTOS) {
                                    //住户userId
                                    String userId = appUsersRemoveDTO.getUserId();
                                    //住户项目数据状态正常时，若住户已被冻结，则无法迁入
                                    Integer userProjectStatus = iPropertyHouseHoldInfoServiceClient.getUserProjectStatusAtNormal(projectId, userId);
                                    if (AppUserProjectStatusEnum.USERPROJECT_USERPROJECTSTATUS_FROZEN.getType() == userProjectStatus) {
                                        continue;
                                    }
                                }
                                //迁入App用户信息
                                iPropertyHouseHoldInfoServiceClient.userMoveIn(appUserUpdateUserRoomStatusDTO, isSmartCommunity,
                                        loginUserId, HouseHoldJPushSceneTypeEnum.HOUSEHOLD_J_PUSH_SCENE_TYPE_MOVE_IN.getType());
                                if (appUserUpdateUserRoomStatusDTO.getRoleIdList() != null && !appUserUpdateUserRoomStatusDTO.getRoleIdList().isEmpty()){
                                    //用户角色组授权
                                    //电梯授权
                                    List<String> oldRoleGroupIdList = iPropertyHouseHoldInfoServiceClient.getOldRoleGroupId(dto.getUserId(), projectId);
                                    dto.getRoleIdList().addAll(oldRoleGroupIdList);
                                    if (!appUsersRemoveDTOS.isEmpty()){
                                        this.userDeviceAuth(appUserUpdateUserRoomStatusDTO.getRoleIdList(), projectId, dto.getUserId(), loginUserId);
                                    }

                                }
                                percent++;
                                project.put(projectId, numberFormat.format((float) percent / (float) count * 100));
                                redisService.set(RedisConstant.PROPERTY_USER_MOVE_PERCENT_KEY + projectId, RedisConstant.PROPERTY_USER_MOVE_PERCENT_CACHE_TIME,
                                        project.get(projectId).toString());
                            }
                        }

                        project.put(projectId, "100");
                        redisService.set(RedisConstant.PROPERTY_USER_MOVE_PERCENT_KEY + projectId, RedisConstant.PROPERTY_USER_MOVE_PERCENT_CACHE_TIME,
                                project.get(projectId).toString());
                        iUserMovePushMessageServiceClient.pushMessage(projectId, token);
                    } else {
                        project.put(projectId, "100");
                        redisService.set(RedisConstant.PROPERTY_USER_MOVE_PERCENT_KEY + projectId, RedisConstant.PROPERTY_USER_MOVE_PERCENT_CACHE_TIME,
                                project.get(projectId).toString());
                        LOG.info("【之前走到这里未执行推送】");
                        iUserMovePushMessageServiceClient.pushMessage(projectId, token);
                    }
                    Thread.sleep(3000);
                } catch (Exception e) {
                    LOG.error(String.format("【批量迁入住户失败，项目id】：%s,\n 迁入数据:%s\n %s\n", projectId, addUsers, moveUsers), e);
                    project.put(projectId, "1");
                    redisService.set(RedisConstant.PROPERTY_USER_MOVE_PERCENT_KEY + projectId, RedisConstant.PROPERTY_USER_MOVE_PERCENT_CACHE_TIME,
                            project.get(projectId).toString());
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e1) {
                    }
                    iUserMovePushMessageServiceClient.pushMessage(projectId, token);
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e1) {
                    }
                    Map<String, Object> param = new HashMap<>();
                    if (!messageVO.getMsgCode().equals(BaseErrorCodeEnum.SUCCESS.getErrorCode().getMainCode())) {
                        param.put("errorMsg",messageVO.getMsg());
                    }
                    redisService.set(RedisConstant.PROPERTY_USER_MOVE_RESULT_KEY + projectId, RedisConstant.PROPERTY_USER_MOVE_RESULT_CACHE_TIME, param);
                    project.put(projectId, "100");
                    redisService.set(RedisConstant.PROPERTY_USER_MOVE_PERCENT_KEY + projectId, RedisConstant.PROPERTY_USER_MOVE_PERCENT_CACHE_TIME,
                            project.get(projectId).toString());
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e1) {
                    }
                } finally {
                    project.put(projectId, null);
                    redisService.del(RedisConstant.PROPERTY_USER_MOVE_PERCENT_KEY + projectId);
                }
            });
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode());
        } catch (Exception e) {
            return new MessageVO(PropertyErrorCodeEnum.IMPORT_EXCEL_ERROR.getErrorCode(), e);
        }
    }

    /**
     * <desc>
     * 添加App用户信息接口
     * <desc/>
     *
     * @param appUserGetUserInfo App用户信息传输数据
     * @param projectId          项目Id
     * @param loginUserId        物业登录账号
     * @return MessageVO 标准格式化响应结果
     * @author zhangs
     * @createDate 2017/09/19
     */
    @LoggerInfo(operateDesc = LogDescConstant.SAVE_APPUSERINFO_LOG_DESC)
    @RequestMapping(path = "/manage/addAppUser", method = RequestMethod.POST)
    @ResponseBody
    public Object addAppUser(
            String appUserGetUserInfo,
            String projectId,
            String loginUserId) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            appUserGetUserInfo = request.getAttribute("appUserGetUserInfo") == null ? null : request.getAttribute("appUserGetUserInfo").toString();
            projectId = request.getAttribute("projectId") == null ? null : request.getAttribute("projectId").toString();
            loginUserId = request.getAttribute("loginUserId") == null ? null : request.getAttribute("loginUserId").toString();
            if (StringUtils.isEmpty(appUserGetUserInfo)) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_USERINFO_NOT_NULL.getErrorCode());
            }
            AppUserGetUserInfoDTO appUserGetUserInfoDTO;
            try {
                appUserGetUserInfoDTO = JSON.parseObject(appUserGetUserInfo, AppUserGetUserInfoDTO.class);
                JSONArray.parseArray(appUserGetUserInfoDTO.getAuthInfo(), AppUserRoomAndRoleInfoDTO.class);
            } catch (Exception e) {
                throw new DataAccessException("【物业系统_住户信息管理_添加住户】数据格式有误", e);
            }
            if (appUserGetUserInfoDTO.getIdCards() != null && !"".equals(appUserGetUserInfoDTO.getIdCards())) {
                appUserGetUserInfoDTO.setIdCards(UserTokenUtil.getPassword(appUserGetUserInfoDTO.getIdCards(), userTokenKey));
            }
            //用户姓名不能为空
            if (StringUtils.isEmpty(appUserGetUserInfoDTO.getRealName())) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_REALNAME_NOT_NULL.getErrorCode());
            }
            //用户手机号不能为空
            String phoneNum = appUserGetUserInfoDTO.getPhoneNum();
            if (StringUtils.isBlank(phoneNum)) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_PHONENUM_NOT_NULL.getErrorCode());
            }
            if (StringUtils.isBlank(projectId)) {
                return new MessageVO(PropertyErrorCodeEnum.PUB_PROJECT_ID_EMPTY_ERR.getErrorCode());
            }
            //查询当前项目信息
            ProjectPO projectPO = iOperateProjectServiceClient.getOneProject(projectId);
            //是否使用云对讲： 0-否，1-是
            Integer isSmartCommunity = projectPO.getIsSmartCommunity();
            //获取项目类型
            String projectType = projectPO.getProjectType();
            //住宅最大授权数，最大为10
            Integer authMaxNum = projectPO.getAuthMaxNum();
            //办公最大授权数，最大为500
            Integer officeAuthMaxNum = projectPO.getOfficeAuthMaxNum();
            if (officeAuthMaxNum == 0) {
                officeAuthMaxNum = 11;
            }
            List<AppUserRoomDTO> appUserRoomDTOS = new ArrayList<>();


            //分解地址授权信息和角色组授权信息
            List<String> roleIdList = this.divideAddressAndRoleAuth(appUserRoomDTOS, appUserGetUserInfoDTO);

//            //用户房间信息不能为空
//            List<AppUserRoomDTO> appUserRoomDTOS = appUserGetUserInfoDTO.getAppUserRoomDTOS();
//            if ((appUserRoomDTOS == null) || (appUserRoomDTOS.size() == 0)) {
//                return new MessageVO(PropertyErrorCodeEnum.APPUSER_USERROOM_NOT_NULL.getErrorCode());
//            }
            //判断新加住户业主房间地址中是否已存在业主
            //Map<String, value> ：isExist业主是否存在，roomNum 业主存在时的房间号,userId 业主userId
            appUserGetUserInfoDTO.setAppUserRoomDTOS(appUserRoomDTOS);
            Map<String, String> resultMap = this.checkOwnerExist(appUserRoomDTOS, null);
            String isExist = resultMap.get("isExist");
            if (StringHandlerUtil.compareStrIgnoreCaseWithOutEmpty("true", isExist)) {
                return new MessageVO(BaseErrorCodeEnum.ERROR.getErrorCode(),
                        "存在房间已有户主", isExist);
            }

            //查询新添加住户是否已存在
            Integer result = iPropertyHouseHoldInfoServiceClient.getAppUserExistStatus(projectId, phoneNum);
            if (result > 0) {
                return new MessageVO(PropertyErrorCodeEnum.INSPECT_USERINFO_EXIST.getErrorCode());
            }
            //获取住户要添加的房间中已入住的用户人数，再跟项目中设置好的房间最大人数比较，超过则不允许添加
            for (AppUserRoomDTO appUserRoomDTO : appUserRoomDTOS) {
                //当前房间中的住户数量
                Integer currentExistCount =
                        iPropertyHouseHoldInfoServiceClient.getMoveInHouseHoldCount(appUserRoomDTO.getRoomId(), projectId);
                //获取该房屋类型 1住宅 2办公
                Integer housesType = iPropertyHouseHoldInfoServiceClient.getHousesType(appUserRoomDTO.getRoomId(), projectId);
                //已达到或超过项目中最大授权人数则无法添加住户
                if ("1".equals(projectType) && currentExistCount >= authMaxNum) {
                    return new MessageVO(BaseErrorCodeEnum.ERROR.getErrorCode(),
                            String.format("%s房间中住户人数已达上限", appUserRoomDTO.getRoomNum()));
                }
                if ("2".equals(projectType) && currentExistCount >= officeAuthMaxNum) {
                    return new MessageVO(BaseErrorCodeEnum.ERROR.getErrorCode(),
                            String.format("%s房间中住户人数已达上限", appUserRoomDTO.getRoomNum()));
                }
            }
            //保存用户信息
            appUserGetUserInfoDTO.setProjectId(projectId);
            appUserGetUserInfoDTO.setUserId(LogicIdUtil.userBusinessId());
            iPropertyHouseHoldInfoServiceClient.addAppUser(appUserGetUserInfoDTO, isSmartCommunity, loginUserId);

            //并给用户授权角色组设备权限
            AppUserInfoPO  appUserInfoPO = iAppMineServiceClient.getUserInfoByPhoneNo(phoneNum);
            if (appUserInfoPO != null && StringUtils.isNotBlank(appUserInfoPO.getUserId())){
                appUserGetUserInfoDTO.setUserId(appUserInfoPO.getUserId());
            }
            this.userDeviceAuth(roleIdList, projectId, appUserGetUserInfoDTO.getUserId(), loginUserId);
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), appUserGetUserInfoDTO.getUserId());
        } catch (Exception e) {
            throw new DataAccessException(String.format("【物业系统_住户信息管理_添加住户】添加住户失败"), e);
        }
    }

    /**
     * <desc>
     * 迁入App用户接口
     * <desc/>
     *
     * @param appUsersMovein 迁入App用户的List
     * @param projectId      项目Id
     * @return MessageVO 标准格式化响应结果
     * @author zhangs
     * @createDate 2017/09/20
     */
    @LoggerInfo(operateDesc = LogDescConstant.USER_MOVEINUSER_INFO_LOG_DESC)
    @RequestMapping(path = "/manage/userMoveIn", method = RequestMethod.POST)
    @ResponseBody
    @AuthAccessRequired
    public Object userMoveIn(
            String appUsersMovein,
            String projectId,
            String loginUserId) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            appUsersMovein = request.getAttribute("appUsersMovein") == null ? null : request.getAttribute("appUsersMovein").toString();
            projectId = request.getAttribute("projectId") == null ? null : request.getAttribute("projectId").toString();
            loginUserId = request.getAttribute("loginUserId") == null ? null : request.getAttribute("loginUserId").toString();
            //迁入用户不能为空
            if (StringUtils.isEmpty(appUsersMovein)) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_USERMEVOIN_NOT_NULL.getErrorCode());
            }
            if (StringUtils.isBlank(projectId)) {
                return new MessageVO(PropertyErrorCodeEnum.PUB_PROJECT_ID_EMPTY_ERR.getErrorCode());
            }
            //解析传入的需迁入的App用户信息
            AppUserUpdateUserRoomStatusDTO appUserUpdateUserRoomStatusDTO;
            try {
                appUserUpdateUserRoomStatusDTO = JSON.parseObject(appUsersMovein, AppUserUpdateUserRoomStatusDTO.class);
            } catch (Exception e) {
                throw new DataAccessException("【物业系统_住户信息管理_迁入住户】数据格式有误", e);
            }
            appUserUpdateUserRoomStatusDTO.setProjectId(projectId);

            List<AppUsersRemoveDTO> appUsersRemoveDTOS = appUserUpdateUserRoomStatusDTO.getAppUsersRemoveDTOList();
            if (appUsersRemoveDTOS.isEmpty()) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_USERROOM_NOT_NULL.getErrorCode());
            }
            //查询当前项目信息
            ProjectPO projectPO = iOperateProjectServiceClient.getOneProject(projectId);
            //是否启用云对讲，默认0,0-否，1-是
            Integer isSmartCommunity = projectPO.getIsSmartCommunity();
            //住宅最大授权数，最大为10
            Integer authMaxNum = projectPO.getAuthMaxNum();
            //办公最大授权数，最大为500
            Integer officeAuthMaxNum = projectPO.getOfficeAuthMaxNum();
            if (officeAuthMaxNum == 0) {
                officeAuthMaxNum = 11;
            }
            //判断迁入住户业主房间地址中是否已存在业主
            Set<String> userIds = new HashSet<>();
            for (AppUsersRemoveDTO appUsersRemoveDTO : appUsersRemoveDTOS) {
                //住户userId
                String userId = appUsersRemoveDTO.getUserId();
                //住户项目数据状态正常时，若住户已被冻结，则无法迁入
                Integer userProjectStatus = iPropertyHouseHoldInfoServiceClient.getUserProjectStatusAtNormal(projectId, userId);
                if (AppUserProjectStatusEnum.USERPROJECT_USERPROJECTSTATUS_FROZEN.getType() == userProjectStatus) {
                    return new MessageVO(PropertyErrorCodeEnum.APPUSER_USERPROJECTSTATUS_FROZEN.getErrorCode());
                }
                List<AppUserRoomDTO> appUserRoomDTOS = appUsersRemoveDTO.getAppUserRoomDTOS();
                //Map<String, value> ：isExist业主是否存在，roomNum 业主存在时的房间号,userId 业主userId
                Map<String, String> resultMap = this.checkOwnerExist(appUserRoomDTOS, userId);
                String isExist = resultMap.get("isExist");
                //房间存在业主，且房间中的业主与当前用户不是同一人时才不允许添加
                if (StringHandlerUtil.compareStrWithOutEmpty("true", isExist) &&
                        !StringHandlerUtil.compareStrWithOutEmpty(userId, resultMap.get("userId"))) {
                    String roomNum = resultMap.get("roomNum");
                    return new MessageVO(BaseErrorCodeEnum.ERROR.getErrorCode(),
                            roomNum + ",该房间下已有户主或管理员", isExist);
                }
                //获取住户要添加的房间中已入住的用户人数，再跟项目中设置好的房间最大人数比较，超过则不允许添加
                for (AppUserRoomDTO appUserRoomDTO : appUserRoomDTOS) {
                    //当前房间中的住户数量
                    Integer currentExistCount =
                            iPropertyHouseHoldInfoServiceClient.getMoveInHouseHoldCount(appUserRoomDTO.getRoomId(), projectId);
                    //获取该房屋类型 1住宅 2办公
                    Integer housesType = iPropertyHouseHoldInfoServiceClient.getHousesType(appUserRoomDTO.getRoomId(), projectId);
                    //已达到或超过项目中最大授权人数则无法添加住户
                    if (housesType == 1 && currentExistCount >= authMaxNum) {
                        return new MessageVO(BaseErrorCodeEnum.ERROR.getErrorCode(),
                                String.format("%s房间中住户人数已达上限", appUserRoomDTO.getRoomNum()));
                    }
                    if (housesType == 3 && currentExistCount >= officeAuthMaxNum) {
                        return new MessageVO(BaseErrorCodeEnum.ERROR.getErrorCode(),
                                String.format("%s房间中住户人数已达上限", appUserRoomDTO.getRoomNum()));
                    }
                }
                userIds.add(userId);
            }

            //迁入App用户信息
            iPropertyHouseHoldInfoServiceClient.userMoveIn(appUserUpdateUserRoomStatusDTO, isSmartCommunity,
                    loginUserId, HouseHoldJPushSceneTypeEnum.HOUSEHOLD_J_PUSH_SCENE_TYPE_MOVE_IN.getType());
            return new MessageVO(StringUtils.join(userIds, ","), BaseErrorCodeEnum.SUCCESS.getErrorCode());
        } catch (Exception e) {
            throw new DataAccessException(String.format("【物业系统_住户信息管理_迁入住户】迁入住户失败"), e);
        }
    }

    /**
     * <desc>
     * 判断添加住户业主房间地址时房间是否已存在业主
     * <desc/>
     *
     * @param appUserRoomDTOS App用户房间信息传输数据集
     * @param userId 要操作的用户id  当userId不为空时，找出有户主且户主 !userId的房间
     * @return Map<String, String> :
     * Map<String, value> isExist业主是否存在，roomNum 业主存在时的房间号,userId 业主userId
     * @author zhangs
     * @createDate 2017/09/20
     */
    private Map<String, String> checkOwnerExist(List<AppUserRoomDTO> appUserRoomDTOS, String userId) {
        Map<String, String> resultMap = new HashMap<>();
        if (appUserRoomDTOS == null || (appUserRoomDTOS.isEmpty())) {
            resultMap.put("isExist", "false");
            return resultMap;
        }
        for (AppUserRoomDTO appUserRoomDTO : appUserRoomDTOS) {
            if (appUserRoomDTO.getHouserType() == AppUserRoomHouserTypeEnum.USERROOM_HOUSERTYPE_OWNER.getType()) {
                AppUserRoomOwnerIsExistDTO appUserRoomOwnerIsExistDTO = new AppUserRoomOwnerIsExistDTO();
                appUserRoomOwnerIsExistDTO.setRoomId(appUserRoomDTO.getRoomId());
                appUserRoomOwnerIsExistDTO.setUserId(userId);
                //获取roomId对应房间是否已存在业主
                List<AppUserRoomPO> appUserRoomPOS =
                        iPropertyHouseHoldInfoServiceClient.getExistHouserByRoom(appUserRoomOwnerIsExistDTO);
                if (appUserRoomPOS != null && appUserRoomPOS.size() > 0) {
                    resultMap.put("isExist", "true");
                    resultMap.put("roomNum", appUserRoomDTO.getRoomNum());
                    resultMap.put("userId", appUserRoomPOS.get(0).getUserId());
                    break;
                }
            }
        }
        return resultMap;
    }

    /**
     * <desc>
     * 查询App用户信息接口(已入住+查询按钮)
     * <desc/>
     *
     * @param checkAppUserDTO 查询App用户信息传输数据
     * @return MessageVO 标准格式化响应结果
     * @author zhangs
     * @createDate 2017/09/20
     */
    @RequestMapping(path = "/manage/getCheckUserList", method = RequestMethod.POST)
    @ResponseBody
    @AuthAccessRequired
    public Object getCheckUserList(CheckAppUserDTO checkAppUserDTO) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            checkAppUserDTO = HttpProtocolUtil.parseRequestParamToDTO(CheckAppUserDTO.class, request);
            if (checkAppUserDTO == null) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_USERINFO_NOT_NULL.getErrorCode());
            }
            if (StringUtils.isBlank(checkAppUserDTO.getProjectId())) {
                return new MessageVO(PropertyErrorCodeEnum.PUB_PROJECT_ID_EMPTY_ERR.getErrorCode());
            }
            if (null == checkAppUserDTO.getUserRoomStatus()) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_USERROOMSTATUS_NOT_NULL.getErrorCode());
            }
            Page<AppUserInfoGetVO> result = iPropertyHouseHoldInfoServiceClient.getCheckUserList(checkAppUserDTO);
            Page<AppUserInfoGetAssembleVO> page = new Page<>();
            page.setPage(result.getPage());
            page.setRows(this.assembleAppUserInfoGetVO(result.getRows(), checkAppUserDTO.getUserRoomStatus()));
            Map<String, Object> appendInfo = iPropertyHouseHoldInfoServiceClient.getAppendInfo(checkAppUserDTO);
            return new MessageVO(JSON.toJSONString(appendInfo), BaseErrorCodeEnum.SUCCESS.getErrorCode(), page);
        } catch (Exception e) {
            throw new DataAccessException(String.format(
                    "【物业系统_住户信息管理_查询住户信息】查询住户信息失败"), e);
        }
    }

    /**
     * <desc>
     * 查询一卡通用户信息接口(一卡通用户+查询按钮)
     * <desc/>
     *
     * @param checkSmartCardUserDTO 查询App用户信息传输数据
     * @return MessageVO 标准格式化响应结果
     * @author zhangs
     * @createDate 2017/12/08
     */
    @RequestMapping(path = "/manage/getCheckSmartCardUserList", method = RequestMethod.POST)
    @ResponseBody
    public Object getCheckSmartCardUserList(CheckSmartCardUserDTO checkSmartCardUserDTO) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            checkSmartCardUserDTO = HttpProtocolUtil.parseRequestParamToDTO(CheckSmartCardUserDTO.class, request);
            if (checkSmartCardUserDTO == null) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_USERINFO_NOT_NULL.getErrorCode());
            }
            if (StringUtils.isBlank(checkSmartCardUserDTO.getProjectId())) {
                return new MessageVO(PropertyErrorCodeEnum.PUB_PROJECT_ID_EMPTY_ERR.getErrorCode());
            }

            Page<AppUserInfoGetVO> result =
                    iPropertyHouseHoldInfoServiceClient.getCheckSmartCardUserList(checkSmartCardUserDTO);
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), result);
        } catch (Exception e) {
            throw new DataAccessException(String.format(
                    "【物业系统_住户信息管理_查询住户信息】查询住户信息失败"), e);
        }
    }

    /**
     * <desc>
     * 修改一卡通用户信息
     * <desc/>
     *
     * @param smartCardUserUpdateDTO 物业后台更新一卡通用户信息数据传输对象
     * @return MessageVO 标准格式化响应结果
     * @author zhangs
     * @createDate 2017/12/08
     */
    @LoggerInfo(operateDesc = LogDescConstant.UPDATE_SMARTCARDUSERINFO_LOG_DESC)
    @RequestMapping(path = "/manage/updateSmartCardUser", method = RequestMethod.POST)
    @ResponseBody
    public Object updateSmartCardUser(SmartCardUserUpdateDTO smartCardUserUpdateDTO) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            smartCardUserUpdateDTO = HttpProtocolUtil.parseRequestParamToDTO(SmartCardUserUpdateDTO.class, request);
            //参数合法性判断
            String projectId = smartCardUserUpdateDTO.getProjectId();
            if (StringUtils.isBlank(projectId)) {
                return new MessageVO(PropertyErrorCodeEnum.PUB_PROJECT_ID_EMPTY_ERR.getErrorCode());
            }
            if (StringUtils.isBlank(smartCardUserUpdateDTO.getLoginUserId())) {
                return new MessageVO(PropertyErrorCodeEnum.PUB_LOGINUSERID_TOKEN_EMPTY_ERR.getErrorCode());
            }
            if (StringUtils.isBlank(smartCardUserUpdateDTO.getUserId())) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_CHOICEUSER_NOT_NULL.getErrorCode());
            }
            if (StringUtils.isEmpty(smartCardUserUpdateDTO.getRealName())) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_REALNAME_NOT_NULL.getErrorCode());
            }
            //查询当前项目信息
            ProjectPO projectPO = iOperateProjectServiceClient.getOneProject(projectId);
            //是否使用云对讲： 0-否，1-是
            Integer isSmartCommunity = projectPO.getIsSmartCommunity();
            iPropertyHouseHoldInfoServiceClient.updateSmartCardUser(smartCardUserUpdateDTO, isSmartCommunity);
            return new MessageVO(smartCardUserUpdateDTO.getUserId(), BaseErrorCodeEnum.SUCCESS.getErrorCode());
        } catch (Exception e) {
            throw new DataAccessException("【物业系统_一卡通用户_更新用户信息】更新用户信息失败", e);
        }
    }


    /**
     * <desc>
     * 组装查询App用户信息返回给前端
     * <desc/>
     *
     * @param appUserInfoGetVOS 返回给前端的物业住户信息对象
     * @return List<AppUserInfoGetAssembleVO> 组装过的返回给前端使用物业住户信息
     * @author zhangs
     * @createDate 2017/09/26
     */
    private List<AppUserInfoGetAssembleVO> assembleAppUserInfoGetVO(List<AppUserInfoGetVO> appUserInfoGetVOS, Integer userRoomStatus) {
        //返回结果
        List<AppUserInfoGetAssembleVO> appUserInfoGetAssembleVOS = new ArrayList<>();
        //用于组装合并数据
        Map<String, AppUserInfoGetAssembleVO> map = new HashMap<>();
        LinkedHashMap<String, AppUserInfoGetAssembleVO> linkedHashMap = new LinkedHashMap<>();
        //记录住户
//        Set<String> userIdSet = new HashSet<>();
        LinkedHashSet<String> userIdSet = new LinkedHashSet<>();
        if (appUserInfoGetVOS.isEmpty()) {
            return appUserInfoGetAssembleVOS;
        }
        //遍历
        for (AppUserInfoGetVO appUserInfoGetVO : appUserInfoGetVOS) {
            String userId = appUserInfoGetVO.getUserId();
            userIdSet.add(userId);
            //相同住户合并住户房间信息
            if (linkedHashMap.get(userId) == null) {
//            if (map.get(userId) == null) {
                List<AppUserInfoGetRoomVO> appUserInfoGetRoomVOS = new ArrayList<>();
                AppUserInfoGetRoomVO appUserInfoGetRoomVO = new AppUserInfoGetRoomVO();
                BeanUtils.copyProperties(appUserInfoGetVO, appUserInfoGetRoomVO);
                appUserInfoGetRoomVOS.add(appUserInfoGetRoomVO);
                AppUserInfoGetAssembleVO appUserInfoGetAssembleVO =
                        new AppUserInfoGetAssembleVO(userId, appUserInfoGetVO.getRealName(), appUserInfoGetVO.getVipFlag(), appUserInfoGetVO.getPhoneNum(),
                                appUserInfoGetVO.getQqNum(), appUserInfoGetVO.getCreateUserTime(),
                                appUserInfoGetVO.getUpdateTime(), appUserInfoGetVO.getIsFace(), appUserInfoGetVO.getIsBindingIdcard(), appUserInfoGetVO.getIsLoss(), appUserInfoGetRoomVOS);
//                map.put(userId, appUserInfoGetAssembleVO);
                if (StringUtils.isNotBlank(appUserInfoGetVO.getFacePicUrl())) {
                    appUserInfoGetAssembleVO.setFacePicUrl(appUserInfoGetVO.getFacePicUrl());
                }
                appUserInfoGetAssembleVO.setRoleName(appUserInfoGetVO.getRoleName());
                linkedHashMap.put(userId, appUserInfoGetAssembleVO);
            } else {
//                AppUserInfoGetAssembleVO appUserInfoGetAssembleVO = map.get(userId);
                AppUserInfoGetAssembleVO appUserInfoGetAssembleVO = linkedHashMap.get(userId);
                List<AppUserInfoGetRoomVO> appUserInfoGetRoomVOS = appUserInfoGetAssembleVO.getAppUserInfoGetRoomVOS();
                AppUserInfoGetRoomVO appUserInfoGetRoomVO = new AppUserInfoGetRoomVO();
                BeanUtils.copyProperties(appUserInfoGetVO, appUserInfoGetRoomVO);
                appUserInfoGetRoomVOS.add(appUserInfoGetRoomVO);
                appUserInfoGetAssembleVO.setAppUserInfoGetRoomVOS(appUserInfoGetRoomVOS);
//                map.put(userId, appUserInfoGetAssembleVO);
                if (StringUtils.isNotBlank(appUserInfoGetVO.getFacePicUrl())) {
                    appUserInfoGetAssembleVO.setFacePicUrl(appUserInfoGetVO.getFacePicUrl());
                }
                linkedHashMap.put(userId, appUserInfoGetAssembleVO);
            }
        }
        for (String userId : userIdSet) {
//            appUserInfoGetAssembleVOS.add(map.get(userId));
            appUserInfoGetAssembleVOS.add(linkedHashMap.get(userId));
        }
        return appUserInfoGetAssembleVOS;
    }

    /**
     * <desc>
     * 查看App用户信息接口(已入住的查看按钮)（弃用）
     * <desc/>
     *
     * @param appUserGetOneDTO 获取单个App用户信息的数据传输对象
     * @return MessageVO 标准格式化响应结果
     * @author zhangs
     * @createDate 2017/09/20
     */
    @RequestMapping(path = "/manage/getUserInfo", method = RequestMethod.POST)
    @ResponseBody
    public Object getUserInfo(AppUserGetOneDTO appUserGetOneDTO) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            appUserGetOneDTO = HttpProtocolUtil.parseRequestParamToDTO(AppUserGetOneDTO.class, request);
            if (appUserGetOneDTO == null) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            String userId = appUserGetOneDTO.getUserId();
            //用户不能为空
            if (StringUtils.isBlank(userId)) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_CHOICEUSER_NOT_NULL.getErrorCode());
            }
            //项目编号
            String projectId = appUserGetOneDTO.getProjectId();
            if (StringUtils.isBlank(projectId)) {
                return new MessageVO(PropertyErrorCodeEnum.PUB_PROJECT_ID_EMPTY_ERR.getErrorCode());
            }
            HouseHoldDetailsInfoDTO appUserGetUserDetailsInfoDTO =
                    iPropertyHouseHoldInfoServiceClient.getUserInfo(appUserGetOneDTO);
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), appUserGetUserDetailsInfoDTO);
        } catch (Exception e) {
            throw new DataAccessException(String.format(
                    "【物业系统_住户信息管理_查看住户信息】查询住户信息失败"), e);
        }
    }

    /**
     * <desc>
     * 修改App用户信息时获取App用户信息
     * <desc/>
     *
     * @param appUserGetOneDTO 获取App用户信息的数据传输对象
     * @return MessageVO 标准格式化响应结果
     * @author zhangs
     * @createDate 2017/09/20
     */
    @RequestMapping(path = "/manage/updateUserGet", method = RequestMethod.POST)
    @ResponseBody
    public Object updateUserGet(AppUserGetOneDTO appUserGetOneDTO) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            appUserGetOneDTO = HttpProtocolUtil.parseRequestParamToDTO(AppUserGetOneDTO.class, request);
            if (appUserGetOneDTO == null) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            System.out.println("【程序进入时间】" + System.currentTimeMillis());
            String userId = appUserGetOneDTO.getUserId();
            //用户不能为空
            if (StringUtils.isBlank(userId)) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_CHOICEUSER_NOT_NULL.getErrorCode());
            }
            //项目编号
            String projectId = appUserGetOneDTO.getProjectId();
            if (StringUtils.isBlank(projectId)) {
                return new MessageVO(PropertyErrorCodeEnum.PUB_PROJECT_ID_EMPTY_ERR.getErrorCode());
            }
            //住户房间状态
            String userRoomStatus = appUserGetOneDTO.getUserRoomStatus();
            if (StringUtils.isBlank(userRoomStatus)) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_USERROOMSTATUS_NOT_NULL.getErrorCode());
            }
            AppUserUpdateUserGetDTO appUserUpdateUserGetDTO =
                    iPropertyHouseHoldInfoServiceClient.updateUserGet(appUserGetOneDTO);
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(),
                    this.assembleAppUserInfoDetail(appUserUpdateUserGetDTO));
        } catch (Exception e) {
            throw new DataAccessException(String.format(
                    "【物业系统_住户信息管理_修改前获取住户户信息】获取住户信息失败"), e);
        }
    }


    /**
     * <desc>
     * 获取用户的楼栋
     * <desc/>
     *
     * @return MessageVO 标准格式化响应结果
     * @author zhangs
     * @createDate 2017/09/20
     */
    @RequestMapping(path = "/manage/getUserBuilds", method = RequestMethod.POST)
    @ResponseBody
    public Object getUserBuilds(String userId, String projectId) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            userId = request.getAttribute("userId") == null ? null : request.getAttribute("userId").toString();
            projectId = request.getAttribute("projectId") == null ? null : request.getAttribute("projectId").toString();
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), iPropertyHouseHoldInfoServiceClient.getUserBuilds(userId, projectId));
        } catch (Exception e) {
            throw new DataAccessException(String.format(
                    "【物业系统_住户信息管理_修改前获取住户户信息】获取用户的楼栋失败"), e);
        }
    }

    /**
     * <desc>
     *      组装修改App用户信息时获取App用户信息返回给前端
     * </desc>
     *
     * @param appUserUpdateUserGetDTO  修改App用户信息时获取App地址及角色组信息
     * @return
     * @Author Zhu.yj
     * @createDate  2021/4/20
     */
    private JSONObject assembleAppUserInfoDetail(AppUserUpdateUserGetDTO appUserUpdateUserGetDTO){

        JSONObject userDetailInfo = new JSONObject();
        //组装基本信息
        userDetailInfo.put("appUserGetUserDetailsDTO", appUserUpdateUserGetDTO.getAppUserGetUserDetailsDTO());
        //将用户的地址信息按人员类型分组展示
        List<AppUserRoomAndRoleInfoDTO> userRoomAndRoleInfoDTOS = new ArrayList<>();
        for (AppUserRoomDetailsDTO appUserRoomDetailsDTO : appUserUpdateUserGetDTO.getAppUserRoomDetailsDTOS()){
            //如果出现用户无房间数据的情况，不返回前端
            if (StringUtils.isBlank(appUserRoomDetailsDTO.getBuildId()) || StringUtils.isBlank(appUserRoomDetailsDTO.getUnitId())
                    || StringUtils.isBlank(appUserRoomDetailsDTO.getRoomId())){
                continue;
            }
            AppUserRoomAndRoleInfoDTO  appUserRoomAndRoleInfoDTO = new AppUserRoomAndRoleInfoDTO();
            appUserRoomAndRoleInfoDTO.setAuthType("1");
            appUserRoomAndRoleInfoDTO.setHouseType(appUserRoomDetailsDTO.getHouserType());
            List<String> singleAddress = new ArrayList<>();
            singleAddress.add(appUserRoomDetailsDTO.getBuildId());
            singleAddress.add(appUserRoomDetailsDTO.getUnitId());
            singleAddress.add(appUserRoomDetailsDTO.getRoomId());
            appUserRoomAndRoleInfoDTO.setAddressList(singleAddress);
            userRoomAndRoleInfoDTOS.add(appUserRoomAndRoleInfoDTO);
        }
        //处理用户的分组权限（分组权限即原角色组权限）
        AppUserRoomAndRoleInfoDTO roleInfoDTO = new AppUserRoomAndRoleInfoDTO();
        //授权方式为2时为分组授权
        if (appUserUpdateUserGetDTO.getRoleIdList() != null && !appUserUpdateUserGetDTO.getRoleIdList().isEmpty()){
            roleInfoDTO.setAuthType("2");
            roleInfoDTO.setRoleIdList(appUserUpdateUserGetDTO.getRoleIdList());
            userRoomAndRoleInfoDTOS.add(roleInfoDTO);
        }
        userDetailInfo.put("userRoomAndRoleInfoDTOS", userRoomAndRoleInfoDTOS);
        System.out.println("【程序出时间】" + System.currentTimeMillis());
        return userDetailInfo;
    }


    /**
     * <desc>
     * 组装修改App用户信息时获取App用户信息返回给前端(已弃用)
     * <desc/>
     *
     * @param appUserUpdateUserGetDTO 修改App用户信息时获取App用户信息
     * @return
     * @author zhangs
     * @createDate 2017/09/26
     */
    private JSONObject assembleAppUserUpdateUserGetDTO(AppUserUpdateUserGetDTO appUserUpdateUserGetDTO) {
        //组装后的结果
        JSONObject result = new JSONObject();

        //组装App用户详情页用户基础信息数据传输对象
        AppUserGetUserDetailsDTO appUserGetUserDetailsDTO = appUserUpdateUserGetDTO.getAppUserGetUserDetailsDTO();
        result.put("appUserGetUserDetailsDTO", appUserGetUserDetailsDTO);

        //组装App用户详情页相关房屋数据传输对象.住户房屋信息组装成树形结构
        List<AppUserRoomDetailsDTO> appUserRoomDetailsDTOS = appUserUpdateUserGetDTO.getAppUserRoomDetailsDTOS();
        if (appUserRoomDetailsDTOS.isEmpty()) {
            result.put("appUserRoomDetailsDTOS", appUserRoomDetailsDTOS);
            return result;
        }
        //组装后的住户房间信息
        JSONArray buildResult = new JSONArray();
        //只有一条住户房间信息
        if (appUserRoomDetailsDTOS.size() == 1) {
            AppUserRoomDetailsDTO appUserRoomDetailsDTO = appUserRoomDetailsDTOS.get(0);
            //房间信息
            JSONObject roomJson = new JSONObject();
            roomJson.put("roomId", appUserRoomDetailsDTO.getRoomId());
            roomJson.put("roomNum", appUserRoomDetailsDTO.getRoomNum());
            roomJson.put("houserType", appUserRoomDetailsDTO.getHouserType());
            roomJson.put("roomName", appUserRoomDetailsDTO.getRoomName());
            roomJson.put("houserTypeName", appUserRoomDetailsDTO.getHouserTypeName());
            roomJson.put("roomType", appUserRoomDetailsDTO.getRoomType());
            JSONArray roomArray = new JSONArray();
            roomArray.add(roomJson);
            //单元信息
            JSONObject unitJson = new JSONObject();
            unitJson.put("unitId", appUserRoomDetailsDTO.getUnitId());
            unitJson.put("unitName", appUserRoomDetailsDTO.getUnitName());
            unitJson.put("roomInfo", roomArray);
            JSONArray unitArray = new JSONArray();
            unitArray.add(unitJson);
            //楼栋信息
            JSONObject buildJson = new JSONObject();
            buildJson.put("buildId", appUserRoomDetailsDTO.getBuildId());
            buildJson.put("buildName", appUserRoomDetailsDTO.getBuildName());
            buildJson.put("unitInfo", unitArray);
            buildResult.add(buildJson);
        } else {    //有多条住户房间信息
            //加入第一条数据
            AppUserRoomDetailsDTO appUserRoomDetailsDTO = appUserRoomDetailsDTOS.get(0);
            //用于比较的buildId
            String buildIdCompare = appUserRoomDetailsDTO.getBuildId();
            //用于比较的unitId
            String unitIdCompare = appUserRoomDetailsDTO.getUnitId();
            //房间信息
            JSONArray roomArray = new JSONArray();
            JSONObject roomJson = new JSONObject();
            roomJson.put("roomId", appUserRoomDetailsDTO.getRoomId());
            roomJson.put("roomNum", appUserRoomDetailsDTO.getRoomNum());
            roomJson.put("houserType", appUserRoomDetailsDTO.getHouserType());
            roomJson.put("houserTypeName", appUserRoomDetailsDTO.getHouserTypeName());
            roomJson.put("roomType", appUserRoomDetailsDTO.getRoomType());
            roomJson.put("roomName", appUserRoomDetailsDTO.getRoomName());
            roomArray.add(roomJson);
            //单元信息
            JSONArray unitArray = new JSONArray();
            JSONObject unitJson = new JSONObject();
            unitJson.put("unitId", appUserRoomDetailsDTO.getUnitId());
            unitJson.put("unitName", appUserRoomDetailsDTO.getUnitName());
            //楼栋信息
            JSONObject buildJson = new JSONObject();
            buildJson.put("buildId", appUserRoomDetailsDTO.getBuildId());
            buildJson.put("buildName", appUserRoomDetailsDTO.getBuildName());
            //遍历住户房间地址信息
            for (int index = 1; index < appUserRoomDetailsDTOS.size(); index++) {
                appUserRoomDetailsDTO = appUserRoomDetailsDTOS.get(index);
                String buildId = appUserRoomDetailsDTO.getBuildId();
                String unitId = appUserRoomDetailsDTO.getUnitId();

                //比较是否是同一栋楼
                if (StringHandlerUtil.compareStrWithOutEmpty(buildIdCompare, buildId)) {
                    //比较是否是同一单元
                    if (StringHandlerUtil.compareStrWithOutEmpty(unitIdCompare, unitId)) {
                        //相同楼栋相同单元的房间合并
                        roomJson = new JSONObject();
                        roomJson.put("roomId", appUserRoomDetailsDTO.getRoomId());
                        roomJson.put("roomNum", appUserRoomDetailsDTO.getRoomNum());
                        roomJson.put("houserType", appUserRoomDetailsDTO.getHouserType());
                        roomJson.put("houserTypeName", appUserRoomDetailsDTO.getHouserTypeName());
                        roomJson.put("roomName", appUserRoomDetailsDTO.getRoomName());
                        roomJson.put("roomType", appUserRoomDetailsDTO.getRoomType());
                        roomArray.add(roomJson);
                    } else {
                        //相同楼栋的单元合并
                        unitJson.put("roomInfo", roomArray);
                        roomArray = new JSONArray();
                        unitArray.add(unitJson);
                        unitJson = new JSONObject();
                        unitJson.put("unitId", appUserRoomDetailsDTO.getUnitId());
                        unitJson.put("unitName", appUserRoomDetailsDTO.getUnitName());
                        unitIdCompare = unitId;

                        roomJson = new JSONObject();
                        roomJson.put("roomId", appUserRoomDetailsDTO.getRoomId());
                        roomJson.put("roomNum", appUserRoomDetailsDTO.getRoomNum());
                        roomJson.put("houserType", appUserRoomDetailsDTO.getHouserType());
                        roomJson.put("roomName", appUserRoomDetailsDTO.getRoomName());
                        roomJson.put("houserTypeName", appUserRoomDetailsDTO.getHouserTypeName());
                        roomJson.put("roomType", appUserRoomDetailsDTO.getRoomType());
                        roomArray.add(roomJson);
                    }
                } else {
                    //不同楼栋的房间合并
                    unitJson.put("roomInfo", roomArray);
                    //房间JSONArray重置
                    roomArray = new JSONArray();
                    roomJson = new JSONObject();
                    roomJson.put("roomId", appUserRoomDetailsDTO.getRoomId());
                    roomJson.put("roomNum", appUserRoomDetailsDTO.getRoomNum());
                    roomJson.put("houserType", appUserRoomDetailsDTO.getHouserType());
                    roomJson.put("roomName", appUserRoomDetailsDTO.getRoomName());
                    roomJson.put("houserTypeName", appUserRoomDetailsDTO.getHouserTypeName());
                    roomJson.put("roomType", appUserRoomDetailsDTO.getRoomType());
                    roomArray.add(roomJson);
                    //不同楼栋的单元合并
                    unitArray.add(unitJson);
                    unitJson = new JSONObject();
                    unitJson.put("unitId", appUserRoomDetailsDTO.getUnitId());
                    unitJson.put("unitName", appUserRoomDetailsDTO.getUnitName());
                    //单元Id重置
                    unitIdCompare = unitId;
                    //楼栋信息合并
                    buildJson.put("unitInfo", unitArray);
                    //单元JSONArray重置
                    unitArray = new JSONArray();
                    buildResult.add(buildJson);
                    buildJson = new JSONObject();
                    buildJson.put("buildId", appUserRoomDetailsDTO.getBuildId());
                    buildJson.put("buildName", appUserRoomDetailsDTO.getBuildName());
                    //楼栋Id重置
                    buildIdCompare = buildId;
                }
                //加入最后一条数据
                if (index == appUserRoomDetailsDTOS.size() - 1) {
                    unitJson.put("roomInfo", roomArray);
                    unitArray.add(unitJson);
                    buildJson.put("unitInfo", unitArray);
                    buildResult.add(buildJson);
                }
            }
        }
        result.put("appUserRoomDetailsDTOS", buildResult);
        return result;
    }

    /**
     * <desc>
     * 修改App用户信息接口
     * <desc/>
     *
     * @param appUserGetUserInfo App用户信息传输数据
     * @param projectId          项目Id
     * @param loginUserId        物业登录账号
     * @return MessageVO 标准格式化响应结果
     * @author zhangs
     * @createDate 2017/09/26
     */
    @LoggerInfo(operateDesc = LogDescConstant.UPDATE_APPUSERINFO_LOG_DESC)
    @RequestMapping(path = "/manage/updateAppUser", method = RequestMethod.POST)
    @AuthAccessRequired
    @ResponseBody
    public Object updateAppUser(
            String appUserGetUserInfo,
            String projectId,
            String loginUserId) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            appUserGetUserInfo = request.getAttribute("appUserGetUserInfo") == null ? null : request.getAttribute("appUserGetUserInfo").toString();
            projectId = request.getAttribute("projectId") == null ? null : request.getAttribute("projectId").toString();
            loginUserId = request.getAttribute("loginUserId") == null ? null : request.getAttribute("loginUserId").toString();
            //参数合法性判断
            if (StringUtils.isBlank(projectId)) {
                return new MessageVO(PropertyErrorCodeEnum.PUB_PROJECT_ID_EMPTY_ERR.getErrorCode());
            }
            if (StringUtils.isEmpty(appUserGetUserInfo)) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_USERINFO_NOT_NULL.getErrorCode());
            }
            AppUserGetUserInfoDTO appUserGetUserInfoDTO;
            try {
                appUserGetUserInfoDTO = JSON.parseObject(appUserGetUserInfo, AppUserGetUserInfoDTO.class);
            } catch (Exception e) {
                throw new DataAccessException("【物业系统_住户信息管理_更新住户信息】数据格式有误", e);
            }
            if (appUserGetUserInfoDTO == null) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_USERINFO_NOT_NULL.getErrorCode());
            }
            appUserGetUserInfoDTO.setProjectId(projectId);
            String userId = appUserGetUserInfoDTO.getUserId();
            if (appUserGetUserInfoDTO.getIdCards() != null && !"".equals(appUserGetUserInfoDTO.getIdCards())) {
                appUserGetUserInfoDTO.setIdCards(UserTokenUtil.getPassword(appUserGetUserInfoDTO.getIdCards(), userTokenKey));
            }
            //用户不能为空
            if (StringUtils.isBlank(userId)) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_CHOICEUSER_NOT_NULL.getErrorCode());
            }
            //用户姓名不能为空
            if (StringUtils.isEmpty(appUserGetUserInfoDTO.getRealName())) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_REALNAME_NOT_NULL.getErrorCode());
            }
            //用户手机号合法性判断
            String phoneNum = appUserGetUserInfoDTO.getPhoneNum();
            if (StringUtils.isBlank(phoneNum)) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_PHONENUM_NOT_NULL.getErrorCode());
            }
            //校验权限信息是否为空
            if (StringUtils.isBlank(appUserGetUserInfoDTO.getAuthInfo())){
                return new MessageVO(PropertyErrorCodeEnum.PROPERTY_AUTH_INFO_NOT_NULL_ERR.getErrorCode());
            }

            List<AppUserRoomDTO> appUserRoomDTOS = new ArrayList<>();

            //分解地址授权信息和角色组授权信息
            List<String> roleIdList = this.divideAddressAndRoleAuth( appUserRoomDTOS, appUserGetUserInfoDTO);

            appUserGetUserInfoDTO.setAppUserRoomDTOS(appUserRoomDTOS);
            //住户项目数据状态正常时，若住户已被冻结，则无法迁入
            Integer userProjectStatus = iPropertyHouseHoldInfoServiceClient.getUserProjectStatusAtNormal(projectId, userId);
            if (AppUserProjectStatusEnum.USERPROJECT_USERPROJECTSTATUS_FROZEN.getType() == userProjectStatus) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_USERPROJECTSTATUS_FROZEN.getErrorCode());
            }
            //判断住户业主房间地址中是否已存在业主
            //Map<String, value> ：isExist业主是否存在，roomNum 业主存在时的房间号,userId 业主userId
            Map<String, String> resultMap = this.checkOwnerExist(appUserRoomDTOS, userId);
            String isExist = resultMap.get("isExist");
            //房间存在业主，且房间中的业主与当前用户不是同一人时才不允许添加
            if (StringHandlerUtil.compareStrIgnoreCaseWithOutEmpty("true", isExist) &&
                    !StringHandlerUtil.compareStrWithOutEmpty(userId, resultMap.get("userId"))) {
                return new MessageVO(BaseErrorCodeEnum.ERROR.getErrorCode(),  "选择的房间下已有户主或管理员", isExist);
            }
            //查询当前项目信息
            ProjectPO projectPO = iOperateProjectServiceClient.getOneProject(projectId);
            //是否使用云对讲： 0-否，1-是
            Integer isSmartCommunity = projectPO.getIsSmartCommunity();

            String projectType = projectPO.getProjectType();
            //住宅最大授权数，最大为10
            Integer authMaxNum = projectPO.getAuthMaxNum();
            //办公最大授权数，最大为500
            Integer officeAuthMaxNum = projectPO.getOfficeAuthMaxNum();
            if (officeAuthMaxNum == 0) {
                officeAuthMaxNum = 11;
            }

            for (AppUserRoomDTO appUserRoomDTO : appUserRoomDTOS) {
                //当前房间中的住户数量
                Integer currentExistCount =
                        iPropertyHouseHoldInfoServiceClient.getMoveInHouseHoldCount(appUserRoomDTO.getRoomId(), projectId);

                Integer userExistCount = iPropertyHouseHoldInfoServiceClient.getUserMoveInHouseHoldCount(appUserRoomDTO.getRoomId(), projectId, userId);
                //获取该房屋类型 1住宅 2办公
                Integer housesType = iPropertyHouseHoldInfoServiceClient.getHousesType(appUserRoomDTO.getRoomId(), projectId);
                //当用户已在房间内时，不校验
                if (userExistCount > 0){
                    continue;
                }
                //已达到或超过项目中最大授权人数则无法添加住户
                if ("1".equals(projectType) && currentExistCount >= authMaxNum) {
                    return new MessageVO(BaseErrorCodeEnum.ERROR.getErrorCode(),
                            String.format("%s房间中住户人数已达上限", appUserRoomDTO.getRoomNum()));
                }
                if ("2".equals(projectType) && currentExistCount >= officeAuthMaxNum) {
                    return new MessageVO(BaseErrorCodeEnum.ERROR.getErrorCode(),
                            String.format("%s房间中住户人数已达上限", appUserRoomDTO.getRoomNum()));
                }
            }

            //查询用户的旧数据，便于判断用户名称及标签是否发生变化后是否向人脸识别系统推送数据
            Map<String, Object> oldUserInfo = iPropertyHouseHoldInfoServiceClient.getOldUserInfo(userId, projectId);
            boolean mark = false;
            if (oldUserInfo != null) {
                String userName = oldUserInfo.get("userName") == null ? "" : oldUserInfo.get("userName") + "";
                String userLable = oldUserInfo.get("userLabel") == null ? "" : oldUserInfo.get("userLabel") + "";
                String newUserLable = appUserGetUserInfoDTO.getUserLabel() == null ? "" : appUserGetUserInfoDTO.getUserLabel();
                String newUserName = appUserGetUserInfoDTO.getRealName() == null ? "" : appUserGetUserInfoDTO.getRealName();
                if (!userName.equals(newUserName) || !userLable.equals(newUserLable)) {
                    mark = true;
                }
            }
            iPropertyHouseHoldInfoServiceClient.updateAppUser(appUserGetUserInfoDTO, loginUserId, isSmartCommunity);

            //分配权限时若角色组不为空，则
            //找出用户原有的角色组
            this.userDeviceAuth(roleIdList, projectId, appUserGetUserInfoDTO.getUserId(), loginUserId);

            String finalProjectId = projectId;
            List<String> userList = new ArrayList<>();
            userList.add(userId);
            boolean finalMark = mark;
            new Thread(() -> {
                try{
                    //为保证权限为最新则休眠4s
                    Thread.sleep(4000);
                    //推送平板指令 先查询出此用户是否已进行人脸认证
                    List<String> userHaveFace = iPropertyHouseholdRoleServiceClient.getUserHaveFace(userList, finalProjectId);
                    if(userHaveFace!=null && userHaveFace.size()>0){
                        //此处处理人脸平板权限指令
                        AppFaceRecognitionDeviceAuthDTO appFaceRecognitionDeviceAuthDTO = new AppFaceRecognitionDeviceAuthDTO();
                        appFaceRecognitionDeviceAuthDTO.setUserIdList(userList);
                        //由于为了共用住户分组主用逻辑，故此处查出的为该用户的权限总集合
                        appFaceRecognitionDeviceAuthDTO.setDeviceUniqueListByRoleId(iPropertyHouseholdRoleServiceClient.getEntranceListByNotInRoleIdAndUserId("",userId,finalProjectId));
                        Map<String,Object> notGroupMap = iPropertyHouseholdRoleServiceClient.getElevatorListByNotInRoleIdAndUserId("",userId,finalProjectId);
                        appFaceRecognitionDeviceAuthDTO.setProjectId(finalProjectId);
                        appFaceRecognitionDeviceAuthDTO.setStatus(1);
                        appFaceRecognitionDeviceAuthDTO.setElevatorListByRoleIdMap(notGroupMap);
                        appFaceRecognitionDeviceAuthDTO.setSleepMark("1");
                        iPadFaceSyncDataServiceClient.padUserAuth(appFaceRecognitionDeviceAuthDTO);

                        //此处处理推送动态人脸识别系统权限指令
                        PadFaceSyncDataDTO padFaceSyncDataDTO = new PadFaceSyncDataDTO();
                        padFaceSyncDataDTO.setOperateType("6");
                        padFaceSyncDataDTO.setAppUserIds(userId);
                        padFaceSyncDataDTO.setProjectId(finalProjectId);
                        padFaceSyncDataDTO.setStatus("1");
                        padFaceSyncDataDTO.setSourceSystem(2);
                        padFaceSyncDataDTO.setSleepMark("1");
                        iPadFaceSyncDataServiceClient.userOrFloorSyncSmartCard(padFaceSyncDataDTO);
                        //此处处理VIP标签若发生变更后 需向动态人脸识别系统推送用户指令
                        if(projectPO.getOnOffLinePadFace() != null && finalMark){
                            PadFaceSyncDataDTO padFaceSyncDataDTO2 = new PadFaceSyncDataDTO();
                            padFaceSyncDataDTO2.setOperateType("5");
                            padFaceSyncDataDTO2.setAppUserIds(userId);
                            padFaceSyncDataDTO2.setProjectId(finalProjectId);
                            padFaceSyncDataDTO2.setSleepMark("1");
                            iPadFaceSyncDataServiceClient.userOrFloorSyncSmartCard(padFaceSyncDataDTO2);
                        }
                    }
                } catch (Exception e) {
                    throw new DataAccessException("【物业-住户管理】修改人员房间或分组向平板或动态人脸识别系统推送指令失败", e);
                }
            }).start();
            return new MessageVO(appUserGetUserInfoDTO.getUserId(), BaseErrorCodeEnum.SUCCESS.getErrorCode());
        } catch (Exception e) {
            throw new DataAccessException(String.format("【物业系统_住户信息管理_更新住户信息】更新住户信息失败"), e);
        }
    }

    /**
     * <desc>
     * 审核App用户信息接口(住户信息中的待审核)
     * <desc/>
     *
     * @param examineUser 审核App用户信息传输数据
     * @param projectId   项目Id
     * @return MessageVO 标准格式化响应结果
     * @author zhangs
     * @createDate 2017/09/25
     */
    @LoggerInfo(operateDesc = LogDescConstant.USER_EXAMINE_INFO_LOG_DESC)
    @RequestMapping(path = "/manage/examineUser", method = RequestMethod.POST)
    @ResponseBody
    @AuthAccessRequired
    public Object examineUser(
            String examineUser,
            String projectId,
            String loginUserId) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            examineUser = request.getAttribute("examineUser") == null ? null : request.getAttribute("examineUser").toString();
            projectId = request.getAttribute("projectId") == null ? null : request.getAttribute("projectId").toString();
            loginUserId = request.getAttribute("loginUserId") == null ? null : request.getAttribute("loginUserId").toString();
            if (StringUtils.isEmpty(examineUser)) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_EXAMINEUSER_NOT_NULL.getErrorCode());
            }
            ExamineHouseHoldDTO examineHouseHoldDTO;
            try {
                examineHouseHoldDTO = JSON.parseObject(examineUser, ExamineHouseHoldDTO.class);
            } catch (Exception e) {
                throw new DataAccessException("【物业系统_住户信息管理_审核住户】数据格式有误", e);
            }
            if (examineHouseHoldDTO == null) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_EXAMINEUSER_ERR.getErrorCode());
            }
            String userId = examineHouseHoldDTO.getUserId();
            //用户不能为空
            if (StringUtils.isBlank(userId)) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_CHOICEUSER_NOT_NULL.getErrorCode());
            }
            //项目编号
            if (StringUtils.isBlank(projectId)) {
                return new MessageVO(PropertyErrorCodeEnum.PUB_PROJECT_ID_EMPTY_ERR.getErrorCode());
            }
            //用户房间状态不能为空
            Integer userRoomStatus = examineHouseHoldDTO.getUserRoomStatus();
            if (userRoomStatus == null) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_USERROOMSTATUS_NOT_NULL.getErrorCode());
            }
            //审核的住户房间信息
            List<AppUserRoomDTO> appUserRoomDTOS = examineHouseHoldDTO.getAppUserRoomDTOS();
            if (appUserRoomDTOS == null || appUserRoomDTOS.size() < 1) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_USERROOM_NOT_NULL.getErrorCode());
            }
            //审核通过需判断住户业主房间地址中是否已存在业主
            if (userRoomStatus == AppUserRoomStatusEnum.USERROOM_STATUS_MOVEIN.getType()) {
                //Map<String, value> ：isExist业主是否存在，roomNum 业主存在时的房间号,userId 业主userId
                Map<String, String> resultMap = this.checkOwnerExist(appUserRoomDTOS, userId);
                String isExist = resultMap.get("isExist");
                //房间存在业主，且房间中的业主与当前用户不是同一人时才不允许添加
                if (StringHandlerUtil.compareStrIgnoreCaseWithOutEmpty("true", isExist) &&
                        !StringHandlerUtil.compareStrWithOutEmpty(userId, resultMap.get("userId"))) {
                    String roomNum = resultMap.get("roomNum");
                    return new MessageVO(BaseErrorCodeEnum.ERROR.getErrorCode(), roomNum + ",该房间下已有户主", isExist);
                }
            }
            //查询当前项目信息
            ProjectPO projectPO = iOperateProjectServiceClient.getOneProject(projectId);
            Integer authMaxNum = projectPO.getAuthMaxNum();
            //办公最大授权数，最大为500
            Integer officeAuthMaxNum = projectPO.getOfficeAuthMaxNum();
            if (officeAuthMaxNum == 0) {
                officeAuthMaxNum = 11;
            }
            String projectType = projectPO.getProjectType();
            Integer isSmartCommunity = projectPO.getIsSmartCommunity();
            //审核通过时需判断房间中已入住的用户人数
            if (userRoomStatus == AppUserRoomStatusEnum.USERROOM_STATUS_MOVEIN.getType()) {
                //获取住户要添加的房间中已入住的用户人数，再跟项目中设置好的房间最大人数比较，超过则不允许添加
                for (AppUserRoomDTO appUserRoomDTO : appUserRoomDTOS) {
                    //当前房间中的住户数量
                    Integer currentExistCount =
                            iPropertyHouseHoldInfoServiceClient.getMoveInHouseHoldCount(appUserRoomDTO.getRoomId(), projectId);
                    //已达到或超过项目中最大授权人数则无法添加住户
                    if (("1".equals(projectType)&& currentExistCount >= authMaxNum) || ("2".equals(projectType) && currentExistCount >= officeAuthMaxNum)) {
                        return new MessageVO(BaseErrorCodeEnum.ERROR.getErrorCode(),
                                String.format("%s房间中住户人数已达上限", appUserRoomDTO.getRoomNum()));
                    }
                }
            }
            //权限变更需极光推送给App信息，推送场景类型
            String sceneType;
            if (AppUserRoomStatusEnum.USERROOM_STATUS_MOVEIN.getType() == userRoomStatus) {
                sceneType = HouseHoldJPushSceneTypeEnum.HOUSEHOLD_J_PUSH_SCENE_TYPE_PASS.getType();
            } else {
                sceneType = HouseHoldJPushSceneTypeEnum.HOUSEHOLD_J_PUSH_SCENE_TYPE_NOT_PASS.getType();
            }
            examineHouseHoldDTO.setInstructionType(16);
            examineHouseHoldDTO.setSourceSystem(2);
            iPropertyHouseHoldInfoServiceClient.examineUser(examineHouseHoldDTO, isSmartCommunity, projectId,
                    loginUserId, sceneType);
            return new MessageVO(examineHouseHoldDTO.getUserId(), BaseErrorCodeEnum.SUCCESS.getErrorCode());
        } catch (Exception e) {
            throw new DataAccessException(String.format("【物业系统_住户信息管理_审核住户】审核住户失败"), e);
        }
    }

    /**
     * <desc>
     * 迁出App用户接口(单个和批量)
     * <desc/>
     *
     * @param appUsersRemove 迁出App用户传输数据
     * @param projectId      项目Id
     * @return MessageVO 标准格式化响应结果
     * @author zhangs
     * @createDate 2017/09/20
     */
    @LoggerInfo(operateDesc = LogDescConstant.USER_REMOVEUSER_INFO_LOG_DESC)
    @RequestMapping(path = "/manage/userRemove", method = RequestMethod.POST)
    @ResponseBody
    @AuthAccessRequired
    public Object userRemove(
            String appUsersRemove,
            String projectId,
            String loginUserId) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            appUsersRemove = request.getAttribute("appUsersRemove") == null ? null : request.getAttribute("appUsersRemove").toString();
            projectId = request.getAttribute("projectId") == null ? null : request.getAttribute("projectId").toString();
            loginUserId = request.getAttribute("loginUserId") == null ? null : request.getAttribute("loginUserId").toString();
            //参数合法性判断
            if (StringUtils.isBlank(projectId)) {
                return new MessageVO(PropertyErrorCodeEnum.PUB_PROJECT_ID_EMPTY_ERR.getErrorCode());
            }
            if (StringUtils.isEmpty(appUsersRemove)) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_USERREMEVO_NOT_NULL.getErrorCode());
            }
            //解析JSON数据
            AppUserUpdateUserRoomStatusDTO appUserUpdateUserRoomStatusDTO;
            try {
                appUserUpdateUserRoomStatusDTO = JSON.parseObject(appUsersRemove, AppUserUpdateUserRoomStatusDTO.class);
            } catch (Exception e) {
                throw new DataAccessException("【物业系统_住户信息管理_迁出住户】数据格式有误", e);
            }
            //迁出用户信息不能为空
            if (appUserUpdateUserRoomStatusDTO == null) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_USERREMEVO_NOT_NULL.getErrorCode());
            }
            List<AppUsersRemoveDTO> appUsersRemoveDTOS = appUserUpdateUserRoomStatusDTO.getAppUsersRemoveDTOList();
            if (appUsersRemoveDTOS == null || appUsersRemoveDTOS.size() < 1) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_USERROOM_NOT_NULL.getErrorCode());
            }
            Set<String> userIds = new HashSet<>();
            for (AppUsersRemoveDTO appUsersRemoveDTO : appUsersRemoveDTOS) {
                String userId = appUsersRemoveDTO.getUserId();
                //住户项目数据状态正常时，若住户已被冻结，则无法迁入
                Integer userProjectStatus = iPropertyHouseHoldInfoServiceClient.getUserProjectStatusAtNormal(projectId, userId);
                if (AppUserProjectStatusEnum.USERPROJECT_USERPROJECTSTATUS_FROZEN.getType() == userProjectStatus) {
                    return new MessageVO(PropertyErrorCodeEnum.APPUSER_USERPROJECTSTATUS_FROZEN.getErrorCode());
                }
                userIds.add(userId);
            }
            //判断是否有未缴费账单,否则不能迁出
            List<AppUsersRemoveDTO> appUsersRemoveDTOList = appUserUpdateUserRoomStatusDTO.getAppUsersRemoveDTOList();
            for (AppUsersRemoveDTO appUsersRemoveDTO : appUsersRemoveDTOList) {
                List<AppUserRoomDTO> appUserRoomDTOList = appUsersRemoveDTO.getAppUserRoomDTOS();
                for (AppUserRoomDTO appUserRoomDTO : appUserRoomDTOList) {
                    if (iPropertyAccountServiceClient.getAccountByRoomId(appUserRoomDTO.getRoomId()) > 0) {
                        return new MessageVO(PropertyErrorCodeEnum.ROOM_ACCOUNT_UNPAY.getErrorCode());
                    }
                }
            }
            //查询当前项目信息
            ProjectPO projectPO = iOperateProjectServiceClient.getOneProject(projectId);
            //是否使用云对讲： 0-否，1-是
            Integer isSmartCommunity = projectPO.getIsSmartCommunity();

            appUserUpdateUserRoomStatusDTO.setProjectId(projectId);
            appUserUpdateUserRoomStatusDTO.setInstructionType(2);
            appUserUpdateUserRoomStatusDTO.setSourceSystem(2);
            iPropertyHouseHoldInfoServiceClient.userRemove(appUserUpdateUserRoomStatusDTO, isSmartCommunity,
                    loginUserId, HouseHoldJPushSceneTypeEnum.HOUSEHOLD_J_PUSH_SCENE_TYPE_MOVE_OUT.getType());
            return new MessageVO(StringUtils.join(userIds, ","), BaseErrorCodeEnum.SUCCESS.getErrorCode());
        } catch (Exception e) {
            throw new DataAccessException(String.format("【物业系统_住户信息管理_迁出住户】迁出住户失败"), e);
        }
    }


    /**
     * <desc>
     * 冻结/解冻App用户状态接口
     * <desc/>
     *
     * @param appUserUpdateUserProjectStatusDTO 更新App用户项目状态数据传输对象
     * @return MessageVO 标准格式化响应结果
     * @author zhangs
     * @createDate 2017/09/29
     */
    @LoggerInfo(operateDesc = LogDescConstant.USER_USERPROJECTSTATUS_INFO_LOG_DESC)
    @RequestMapping(path = "/manage/userProjectStatus", method = RequestMethod.POST)
    @ResponseBody
    @AuthAccessRequired
    public Object userProjectStatus(AppUserUpdateUserProjectStatusDTO appUserUpdateUserProjectStatusDTO) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            appUserUpdateUserProjectStatusDTO = HttpProtocolUtil.parseRequestParamToDTO(AppUserUpdateUserProjectStatusDTO.class, request);
            //参数合法性判断
            if (appUserUpdateUserProjectStatusDTO == null) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            String userIds = appUserUpdateUserProjectStatusDTO.getUserIds();
            if (StringUtils.isBlank(userIds)) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_USERPROJECTSTATUS_NOT_NULL.getErrorCode());
            }
            String projectId = appUserUpdateUserProjectStatusDTO.getProjectId();
            if (StringUtils.isBlank(projectId)) {
                return new MessageVO(PropertyErrorCodeEnum.PUB_PROJECT_ID_EMPTY_ERR.getErrorCode());
            }
            String userProjectStatus = appUserUpdateUserProjectStatusDTO.getUserProjectStatus();
            if (StringUtils.isBlank(userProjectStatus)) {
                return new MessageVO(PropertyErrorCodeEnum.USERPROJECTSTATUS_STATUS_NOT_NULL.getErrorCode());
            }
            //查询当前项目信息
            ProjectPO projectPO = iOperateProjectServiceClient.getOneProject(projectId);
            appUserUpdateUserProjectStatusDTO.setProjectName(projectPO.getProjectName());
            appUserUpdateUserProjectStatusDTO.setIsSmartCommunity(projectPO.getIsSmartCommunity());
            appUserUpdateUserProjectStatusDTO.setInstructionType(0);
            appUserUpdateUserProjectStatusDTO.setSourceSystem(2);
            //更新用户项目状态
            iPropertyHouseHoldInfoServiceClient.userProjectStatus(appUserUpdateUserProjectStatusDTO);
            // 平板优先离线，则插入同步数据
            if (projectPO.getOnOffLinePadFace() != null) {
                PadFaceSyncDataDTO padFaceSyncDataDTO = new PadFaceSyncDataDTO();
                padFaceSyncDataDTO.setOperateType("0");
                padFaceSyncDataDTO.setAppUserIds(userIds);
                padFaceSyncDataDTO.setProjectId(projectId);
                padFaceSyncDataDTO.setSourceSystem(2);
                // 用户禁用启用状态 1正常 5禁用 4冻结 2欠费
                if (projectPO.getOnOffLinePadFace() == 1) {
                    padFaceSyncDataDTO.setStatus("1".equals(userProjectStatus) ? "1" : "4");
                    iPadFaceSyncDataServiceClient.userOrFloorSync(padFaceSyncDataDTO);
                }
                padFaceSyncDataDTO.setStatus("1".equals(userProjectStatus) ? "1" : "2");
                iPadFaceSyncDataServiceClient.userOrFloorSyncSmartCard(padFaceSyncDataDTO);
            }
            return new MessageVO(appUserUpdateUserProjectStatusDTO.getUserIds(), BaseErrorCodeEnum.SUCCESS.getErrorCode());
        } catch (Exception e) {
            throw new DataAccessException(String.format(
                    "【物业系统_住户信息管理_冻结/解冻住户】冻结/解冻住户失败"), e);
        }
    }

    /**
     * <desc>
     * 删除用户房间关系(住户信息-未通过-删除,支持批量删除)
     * 若只传userId而没有住户地址则删除所有该项目下该住户地址为未通过的住户房间信息
     * <desc/>
     *
     * @param appUserDelUserRooms App用户房间信息数据集
     * @return MessageVO 标准格式化响应结果
     * @author zhangs
     * @createDate 2017/09/30
     */
    @LoggerInfo(operateDesc = LogDescConstant.DEL_APPUSERROOM_LOG_DESC)
    @RequestMapping(path = "manage/delUserRoom", method = RequestMethod.POST)
    @ResponseBody
    public Object delUserRoom(
            String appUserDelUserRooms, String projectId) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            appUserDelUserRooms = request.getAttribute("appUserDelUserRooms") == null ? null : request.getAttribute("appUserDelUserRooms").toString();
            projectId = request.getAttribute("projectId") == null ? null : request.getAttribute("projectId").toString();
            //参数合法性判断
            if (StringUtils.isBlank(projectId)) {
                return new MessageVO(PropertyErrorCodeEnum.PUB_PROJECT_ID_EMPTY_ERR.getErrorCode());
            }
            if (StringUtils.isEmpty(appUserDelUserRooms)) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_USERROOM_NOT_NULL.getErrorCode());
            }
            //解析App用户房间信息数据
            List<AppUserDelUserRoomDTO> appUserDelUserRoomDTOS;
            try {
                appUserDelUserRoomDTOS = JSON.parseArray(appUserDelUserRooms, AppUserDelUserRoomDTO.class);
            } catch (Exception e) {
                throw new DataAccessException("【物业系统_住户信息管理_删除住户房间信息】数据格式有误", e);
            }
            if (appUserDelUserRoomDTOS.size() == 0) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_USERROOM_NOT_NULL.getErrorCode());
            }
            List<String> userIds = new ArrayList<>();
            for (AppUserDelUserRoomDTO appUserDelUserRoomDTO : appUserDelUserRoomDTOS) {
                String userId = appUserDelUserRoomDTO.getUserId();
                if (StringUtils.isBlank(userId)) {
                    return new MessageVO(PropertyErrorCodeEnum.APPUSER_USERPROJECTSTATUS_NOT_NULL.getErrorCode());
                }
                userIds.add(userId);
                Integer userRoomStatus = appUserDelUserRoomDTO.getUserRoomStatus();
                if (userRoomStatus == null) {
                    return new MessageVO(PropertyErrorCodeEnum.APPUSER_USERROOMSTATUS_NOT_NULL.getErrorCode());
                }
            }
            //删除App用户房间信息数据
            Integer result = iPropertyHouseHoldInfoServiceClient.delUserRoom(appUserDelUserRoomDTOS, projectId);
            if (result > 0) {
                return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode());
            } else {
                return new MessageVO(PropertyErrorCodeEnum.DEL_USERROOMINFO_ERR.getErrorCode());
            }
        } catch (Exception e) {
            throw new DataAccessException(String.format(
                    "【物业系统_住户信息管理_删除住户房间信息】删除住户房间信息失败"), e);
        }
    }

    /**
     * <desc>
     * 设备授权-获取用户设备权限
     * <desc/>
     *
     * @param propertyEquipAuthGetDTO 设备授权时分页获取设备信息的数据传输对象
     * @return MessageVO 标准格式化响应结果
     * @author zhangs
     * @createDate 2017/10/10
     */
    @RequestMapping(path = "manage/getUserDeviceAuth", method = RequestMethod.POST)
    @ResponseBody
    public Object getUserDeviceAuth(PropertyEquipAuthGetDTO propertyEquipAuthGetDTO) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            propertyEquipAuthGetDTO = HttpProtocolUtil.parseRequestParamToDTO(PropertyEquipAuthGetDTO.class, request);
            //参数合法性判断
            if (propertyEquipAuthGetDTO == null) {
                return new MessageVO(PropertyErrorCodeEnum.PUB_PROJECT_ID_EMPTY_ERR.getErrorCode());
            }
            String userId = propertyEquipAuthGetDTO.getUserId();
            if (StringUtils.isBlank(userId)) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_USERPROJECTSTATUS_NOT_NULL.getErrorCode());
            }
            String projectId = propertyEquipAuthGetDTO.getProjectId();
            if (StringUtils.isBlank(projectId)) {
                return new MessageVO(PropertyErrorCodeEnum.PUB_PROJECT_ID_EMPTY_ERR.getErrorCode());
            }
            //判断设备类型
            Integer deviceType = propertyEquipAuthGetDTO.getDeviceType();
            PropertyEquipTypeEnum equipTypeEnum = PropertyEquipTypeEnum.getByEquipType(deviceType);
            if (equipTypeEnum.getType() == -1) {
                return new MessageVO(PropertyErrorCodeEnum.EQUIP_DEVICETYPE_IS_ILLEGAL.getErrorCode());
            }

//            //若是查询云对讲设备权限则只显示住户所在地址(包含楼栋)对应的云对讲设备
//            if ((deviceType != PropertyEquipTypeEnum.ELEVATOR.getType()) && (deviceType != PropertyEquipTypeEnum.ENTRANCE.getType())) {
//                //获取住户地址信息(住户所在楼栋)
//                String buildIds = iPropertyHouseHoldInfoServiceClient.getBuildIdsByHouseHold(userId, projectId);
//                if (StringUtils.isNotBlank(buildIds)) {
//                    propertyEquipAuthGetDTO.setBuildId(buildIds);
//                }
//            }

            //分页获取设备信息
            Page<PropertyEquipSimpleVO> page = iPropertyEquipServiceClient.getUserEquipAuthByPage(propertyEquipAuthGetDTO);
            if (page == null) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_DEVICEAUTH_ERR.getErrorCode());
            }
            //整合返回的设备授权时分页获取设备信息的数据和用户设备权限数据
            List<PropertyEquipSimpleVO> lists = page.getRows();
            //整理获取自设备服务端的设备信息
            //获取用户设备权限
            List<AppUserGetDeviceAuthVO> appUserGetDeviceAuthVOS =
                    iPropertyDeviceAuthServiceClient.getUserDeviceAuth(userId, projectId, deviceType.toString());

            //用户设备权限集合，用于比对当前页面有权限的设备
            Map<String, AppUserGetDeviceAuthVO> appUserGetDeviceAuthVOMap = new HashMap<>();
            for (AppUserGetDeviceAuthVO appUserGetDeviceAuthVO : appUserGetDeviceAuthVOS) {
                appUserGetDeviceAuthVOMap.put(appUserGetDeviceAuthVO.getDeviceUnique(), appUserGetDeviceAuthVO);
            }
            for (PropertyEquipSimpleVO equip : lists) {
                List<PropertyElevatorFloorVO> propertyElevatorFloorVOS = new ArrayList<>();
                String deviceUnique = equip.getDeviceUnique();
                AppUserGetDeviceAuthVO appUserGetDeviceAuthVO = appUserGetDeviceAuthVOMap.get(deviceUnique);
                //由地址获得的设备权限不允许编辑，同时电梯权限楼层需精确到楼层
                if (deviceType == PropertyEquipTypeEnum.ELEVATOR.getType()) {
                    //电梯设备权限
                    List<DeviceElevatorFloorConfigPO> floorConfigPOS = equip.getFloorConfigs();
                    if ((null == floorConfigPOS) || (floorConfigPOS.isEmpty())) {
                        continue;
                    }
                    //设置楼层权限
                    if (appUserGetDeviceAuthVO != null){
                        equip.setFloors(appUserGetDeviceAuthVO.getNaturalFloor());
                    }
                    for (DeviceElevatorFloorConfigPO floorConfig : floorConfigPOS) {
                        PropertyElevatorFloorVO propertyElevatorFloorVO = new PropertyElevatorFloorVO();
                        propertyElevatorFloorVO.setDeviceUnique(deviceUnique);
                        propertyElevatorFloorVO.setFloorName(floorConfig.getLogicalFloor());
                        propertyElevatorFloorVO.setNaturalFloor(floorConfig.getNaturalFloor());
                        propertyElevatorFloorVO.setIsChecked(String.valueOf(PlatformConstants.DEVICEAUTH_ISCHECKED_YET));
                        //电梯设备权限信息，需精确到楼层
                        if (appUserGetDeviceAuthVO != null) {
                            String logicalFloors = appUserGetDeviceAuthVO.getLogicalFloor();
                            String tempFloors = appUserGetDeviceAuthVO.getTempFloor();
                            if (StringUtils.isBlank(logicalFloors) && StringUtils.isBlank(tempFloors)) {
                                continue;
                            }
                            List<String> logicalFloorList = new ArrayList<>();
                            if (StringUtils.isNotBlank(logicalFloors)) {
                                logicalFloorList = Arrays.asList(logicalFloors.split(","));
                            }
                            List<String> tempFloorList = new ArrayList<>();
                            if (StringUtils.isNotBlank(tempFloors)) {
                                tempFloorList = Arrays.asList(tempFloors.split(","));
                            }
                            if (logicalFloorList != null && logicalFloorList.size() > 0 && logicalFloorList.indexOf(floorConfig.getLogicalFloor()) > -1) {
                                propertyElevatorFloorVO.setIsChecked(String.valueOf(PlatformConstants.DEVICEAUTH_ISCHECKED_NO));
                            } else if (tempFloorList != null && tempFloorList.size() > 0 && tempFloorList.indexOf(floorConfig.getLogicalFloor()) > -1) {
                                propertyElevatorFloorVO.setIsChecked(String.valueOf(PlatformConstants.DEVICEAUTH_ISCHECKED_YSE));
                            }

                        }
                        propertyElevatorFloorVOS.add(propertyElevatorFloorVO);
                    }
                }
                if (appUserGetDeviceAuthVO != null) {
                    if (appUserGetDeviceAuthVO.getIsChecked() != null) {
                        equip.setIsChecked(String.valueOf(appUserGetDeviceAuthVO.getIsChecked()));
                    } else {
                        equip.setIsChecked(String.valueOf(PlatformConstants.DEVICEAUTH_ISCHECKED_YET));
                    }
                } else {
                    equip.setIsChecked(String.valueOf(PlatformConstants.DEVICEAUTH_ISCHECKED_YET));
                }
                equip.setPropertyElevatorFloorVOS(propertyElevatorFloorVOS);
                equip.setFloorConfigs(null); //将楼层对应表信息置为null,减少给前端的数据传输
            }
            page.setRows(lists);
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), page);
        } catch (Exception e) {
            throw new DataAccessException(String.format(
                    "【物业系统_住户信息管理_获取用户设备权限】获取设备权限失败"), e);
        }
    }

    /**
     * <desc>
     * 设备授权-更新用户设备权限
     * <desc/>
     *
     * @param loginUserId    用户登录Id
     * @param userId         用户Id
     * @param projectId      项目Id
     * @param currentDevices 前端页面返回的当前页面所有设备唯一码集(英文逗号拼接)
     * @param selectDevices  前端页面返回的当前页面选中设备唯一码集(英文逗号拼接)
     * @param naturalFloors  选中电梯设备时传输的楼层信息
     * @return MessageVO 标准格式化响应结果
     * @author zhangs
     * @createDate 2017/10/10
     */
    @LoggerInfo(operateDesc = LogDescConstant.USER_UPDATEDEVICEAUTH_LOG_DESC)
    @RequestMapping(path = "manage/updateOtherUserDeviceAuth", method = RequestMethod.POST)
    @ResponseBody
    @AuthAccessRequired
    public Object updateUserDeviceAuth(
            String loginUserId,
            String userId,
            String projectId,
            String currentDevices,
            String selectDevices,
            String naturalFloors) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            loginUserId = request.getAttribute("loginUserId") == null ? null : request.getAttribute("loginUserId").toString();
            userId = request.getAttribute("userId") == null ? null : request.getAttribute("userId").toString();
            projectId = request.getAttribute("projectId") == null ? null : request.getAttribute("projectId").toString();
            currentDevices = request.getAttribute("currentDevices") == null ? null : request.getAttribute("currentDevices").toString();
            selectDevices = request.getAttribute("selectDevices") == null ? null : request.getAttribute("selectDevices").toString();
            naturalFloors = request.getAttribute("naturalFloors") == null ? null : request.getAttribute("naturalFloors").toString();
            //参数合法性判断
            if (StringUtils.isBlank(loginUserId)) {
                return new MessageVO(PropertyErrorCodeEnum.PUB_LOGINUSERID_TOKEN_EMPTY_ERR.getErrorCode());
            }
            if (StringUtils.isBlank(userId)) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_USERPROJECTSTATUS_NOT_NULL.getErrorCode());
            }
            if (StringUtils.isBlank(projectId)) {
                return new MessageVO(PropertyErrorCodeEnum.PUB_PROJECT_ID_EMPTY_ERR.getErrorCode());
            }
            if (StringUtils.isBlank(currentDevices)) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_DEVICEINFO_ERR.getErrorCode());
            }
            //去掉设备权限时该参数为空
            /*if(StringUtils.isBlank(selectDevices)) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_DEVICEINFO_ERR.getErrorCode());
            }*/
            String[] deviceUniques = currentDevices.split(",");
            Integer deviceType = StringHandlerUtil.strToIntDef(
                    StringHandlerUtil.copySubStr(deviceUniques[0], 8, 1), -1);
            if (deviceType == -1) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_DEVICEINFO_ERR.getErrorCode());
            }
            //若是电梯设备且有选中设备则楼层信息不会为空，解析后的楼层信息naturalfloorList的size应和选中电梯设备数量一致
            List<String> naturalfloorList = new ArrayList<>();
            if (deviceType == PropertyEquipTypeEnum.ELEVATOR.getType()) {
                List<String> naturalfloors;
                try {
                    naturalfloors = JSON.parseArray(naturalFloors, String.class);
                } catch (Exception e) {
                    throw new DataAccessException("【物业系统_住户信息管理_更新用户设备权限】数据格式有误", e);
                }

                currentDevices = iPropertyHouseholdRoleServiceClient.getDeviceUniqueIdList(currentDevices, projectId).trim();
                String[] deviceArr = StringHandlerUtil.splitString(selectDevices);
                //此处处理通过筛选条件只变更群控器下的一个电梯，此时群控器下的其他电梯也需一块处理
                for(String elevator:deviceArr){
                    List<String> list = iPropertyHouseholdRoleServiceClient.getCloudControllerElevatorInfo(elevator);
                    if(list!=null && naturalFloors != null && naturalFloors.length() > 0 && selectDevices != null){
                        for(String deviceUnique : list){
                            if(!selectDevices.contains(deviceUnique)){
                                selectDevices = selectDevices+ ","+deviceUnique;
                                String naturalFloor = naturalFloors;
                                naturalFloors = naturalFloor.substring(0,naturalFloor.length()-1)+",'"+naturalfloors.get(Arrays.asList(deviceArr).indexOf(elevator))+"']";
                            }
                        }
                    }
                }

                try {
                    naturalfloors = JSON.parseArray(naturalFloors, String.class);
                } catch (Exception e) {
                    throw new DataAccessException("【物业系统_住户信息管理_更新用户设备权限】数据格式有误", e);
                }

                //移除未选择楼层的项
                for (int floorIndex = naturalfloors.size() - 1; floorIndex >= 0; floorIndex--) {
                    if (StringUtils.isNotBlank(naturalfloors.get(floorIndex))) {
                        naturalfloorList.add(naturalfloors.get(floorIndex));
                    }
                }
                //楼层是否为空
                boolean isNull = false;
                if (naturalfloorList != null && naturalfloorList.size() > 0) {
                    for (String naturalFloor : naturalfloorList) {
                        if (StringUtils.isBlank(naturalFloor)) {
                            isNull = true;
                        }
                    }
                } else {
                    isNull = true;
                }
                //电梯设备机号和楼层不同时为空时有误
                if ((StringUtils.isNotBlank(selectDevices) && selectDevices.replace(",", "").length() > 0 && isNull)
                        || (StringUtils.isBlank(selectDevices) && !isNull)) {
                    return new MessageVO(PropertyErrorCodeEnum.APPUSER_DEVICEINFO_ELEVATOR_FLOOR_ERR.getErrorCode());
                }
                //同时不为空，判断数量是否相同
                if (StringUtils.isBlank(selectDevices) && !isNull) {
                    List<String> selectDeviceList = new ArrayList<>();
                    List<String> selectDevice = Arrays.asList(selectDevices.split(","));
                    //移除未选择设备的项
                    for (int floorIndex = selectDevice.size() - 1; floorIndex >= 0; floorIndex--) {
                        if (StringUtils.isNotBlank(selectDevice.get(floorIndex))) {
                            selectDeviceList.add(selectDevice.get(floorIndex));
                        }
                    }
                    if (selectDeviceList.size() != naturalfloorList.size()) {
                        return new MessageVO(PropertyErrorCodeEnum.APPUSER_DEVICEINFO_ELEVATOR_FLOOR_ERR.getErrorCode());
                    }
                }
            }
            //住户项目数据状态正常时，若住户已被冻结，则无法迁入
            Integer userProjectStatus = iPropertyHouseHoldInfoServiceClient.getUserProjectStatusAtNormal(projectId, userId);
            if (AppUserProjectStatusEnum.USERPROJECT_USERPROJECTSTATUS_FROZEN.getType() == userProjectStatus) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_USERPROJECTSTATUS_FROZEN.getErrorCode());
            }
            //获取用户临时权限数据
            Map<String, Object> tempAuth = iPropertyHouseHoldInfoServiceClient.getOldUserTempAuth(userId, projectId);
            //家半径临时授权（包括住户管理设备授权和家半径一卡通用户授权）
            iPropertyDeviceAuthServiceClient.updateHouseHoldTmpDeviceAuth(loginUserId, userId, projectId, deviceType, currentDevices,
                    selectDevices, naturalfloorList, "noMark");
            //推送平板用户数据
            iPropertyHouseHoldInfoServiceClient.pushPadUserInfos(projectId, userId, StringHandlerUtil.getNullOrStringForObject(tempAuth.get("doorAuth")),
                    StringHandlerUtil.getNullOrStringForObject(tempAuth.get("elevatorAuth")), StringHandlerUtil.getNullOrStringForObject(tempAuth.get("talkAuth")));
            //推送用户临时权限
            iPropertyHouseHoldInfoServiceClient.pushTempUserInfos(projectId, userId, StringHandlerUtil.getNullOrStringForObject(tempAuth.get("doorAuth")),
                    StringHandlerUtil.getNullOrStringForObject(tempAuth.get("elevatorAuth")), StringHandlerUtil.getNullOrStringForObject(tempAuth.get("talkAuth")),"");

            // 查询该用户是否有人脸，如有人脸则向动态人脸识别系统推送指令

            if (iPropertyHouseHoldInfoServiceClient.isFaceUrlByUserIdAndProjectId(userId,projectId)>0) {
                PadFaceSyncDataDTO padFaceSyncDataDTO = new PadFaceSyncDataDTO();
                padFaceSyncDataDTO.setOperateType("6");
                padFaceSyncDataDTO.setAppUserIds(userId);
                padFaceSyncDataDTO.setProjectId(projectId);
                padFaceSyncDataDTO.setStatus("1");
                padFaceSyncDataDTO.setSourceSystem(2);
                iPadFaceSyncDataServiceClient.userOrFloorSyncSmartCard(padFaceSyncDataDTO);
            }

            return new MessageVO(userId, BaseErrorCodeEnum.SUCCESS.getErrorCode());
        } catch (Exception e) {
            throw new DataAccessException(String.format(
                    "【物业系统_住户信息管理_更新住户设备权限】更新住户设备权限失败"), e);
        }
    }

    /**
     * <desc>
     * 判断房间下是否已有业主
     * <desc/>
     *
     * @param appUserRoomOwnerIsExistDTO 房间中是否存在业主状态的数据传输对象
     * @return MessageVO 标准格式化响应结果
     * @author zhangs
     * @createDate 2017/10/19
     */
    @RequestMapping(path = "manage/getExistHouserByRoom", method = RequestMethod.POST)
    @ResponseBody
    public Object getExistHouseByRoom(AppUserRoomOwnerIsExistDTO appUserRoomOwnerIsExistDTO) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            appUserRoomOwnerIsExistDTO = HttpProtocolUtil.parseRequestParamToDTO(AppUserRoomOwnerIsExistDTO.class, request);
            if (appUserRoomOwnerIsExistDTO == null) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            Integer houserType = appUserRoomOwnerIsExistDTO.getHouserType();
            //住户身份类型
            if (houserType == null) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_HOUSERTYPE_NOT_NULL.getErrorCode());
            }
            //仅判断选择业主身份时房间下是否已存在业主
            if (houserType != AppUserRoomHouserTypeEnum.USERROOM_HOUSERTYPE_OWNER.getType()) {
                return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode());
            }
            String roomId = appUserRoomOwnerIsExistDTO.getRoomId();
            if (StringUtils.isBlank(roomId)) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_ROOM_NOT_NULL.getErrorCode());
            }
            List<AppUserRoomPO> appUserRoomPOS = iPropertyHouseHoldInfoServiceClient.getExistHouserByRoom(appUserRoomOwnerIsExistDTO);
            if (appUserRoomPOS != null && appUserRoomPOS.size() > 0) {
                return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), "该房间下已有户主或管理员", true);
            } else {
                return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), "该房间下没有户主或管理员", false);
            }
        } catch (Exception e) {
            throw new DataAccessException(String.format(
                    "【物业系统_住户信息管理_判断房间下是否已有业主】判断房间下是否已有业主失败"), e);
        }
    }

    /**
     * <desc>
     * 获取未与用户绑定的房间地址
     * <desc/>
     *
     * @param appUserGetNotContactRoomDTO 未与用户绑定的地址信息数据传输对象
     * @return MessageVO 标准格式化响应结果
     * @author zhangs
     * @createDate 2017/10/20
     */
    @RequestMapping(path = "manage/getRoomNotContactHouse", method = RequestMethod.POST)
    @ResponseBody
    public Object getRoomNotContactHouse(AppUserGetNotContactRoomDTO appUserGetNotContactRoomDTO) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            appUserGetNotContactRoomDTO = HttpProtocolUtil.parseRequestParamToDTO(AppUserGetNotContactRoomDTO.class, request);
            //参数合法性判断
            if (appUserGetNotContactRoomDTO == null) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            String projectId = appUserGetNotContactRoomDTO.getProjectId();
            if (StringUtils.isBlank(projectId)) {
                return new MessageVO(PropertyErrorCodeEnum.PUB_PROJECT_ID_EMPTY_ERR.getErrorCode());
            }
            String unitId = appUserGetNotContactRoomDTO.getUnitId();
            if (StringUtils.isBlank(unitId)) {
                return new MessageVO(PropertyErrorCodeEnum.PROJECT_UNIT_ID_EMPTY_ERR.getErrorCode());
            }
            String userId = appUserGetNotContactRoomDTO.getUserId();
            if (StringUtils.isBlank(userId)) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_USERPROJECTSTATUS_NOT_NULL.getErrorCode());
            }
            //未与用户绑定的房间信息集
            List<PropertyProjectRoomSimpleInfoVO> propertyProjectRoomSimpleInfoVOS;
            //获取用户房间地址信息
            List<AppUserGetContractRoomDTO> appUserGetContractRoomDTOS =
                    iPropertyHouseHoldInfoServiceClient.getRoomContactHouser(appUserGetNotContactRoomDTO);

            //查询指定单元下的排除部分房间的其它所有房屋简单信息（房屋ID，房屋名称）数据传输对象
            PropertyProjectGetRoomSimpleInfoExcludeIdsDTO propertyProjectGetRoomSimpleInfoExcludeIdsDTO =
                    new PropertyProjectGetRoomSimpleInfoExcludeIdsDTO();
            List<String> excludeRoomIds = new ArrayList<>();
            if (!appUserGetContractRoomDTOS.isEmpty()) {
                for (AppUserGetContractRoomDTO appUserGetContractRoomDTO : appUserGetContractRoomDTOS) {
                    excludeRoomIds.add(appUserGetContractRoomDTO.getRoomId());
                }
            }
            propertyProjectGetRoomSimpleInfoExcludeIdsDTO.setUnitId(unitId);
            propertyProjectGetRoomSimpleInfoExcludeIdsDTO.setExcludeRoomIds(excludeRoomIds);
            propertyProjectGetRoomSimpleInfoExcludeIdsDTO.setCurrentPage(appUserGetNotContactRoomDTO.getCurrentPage());
            propertyProjectGetRoomSimpleInfoExcludeIdsDTO.setPageSize(appUserGetNotContactRoomDTO.getPageSize());
            //获取未与用户绑定的房间地址
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), iPropertyRoomInfoServiceClient.getRoomSimpleInfoExcludeIds(propertyProjectGetRoomSimpleInfoExcludeIdsDTO));
        } catch (Exception e) {
            throw new DataAccessException(String.format(
                    "【物业系统_住户信息管理_获取未与住户绑定的房间地址】获取未与住户绑定的房间地址失败"), e);
        }
    }

    /**
     * <desc>
     * 获取未与用户完全绑定的楼栋地址(获取不是所有房屋都与住户绑定的楼栋地址)
     * <desc/>
     *
     * @param userId    住户Id
     * @param projectId 项目Id
     * @return MessageVO 标准格式化响应结果
     * @author zhangs
     * @createDate 2017/11/10
     */
    @RequestMapping(path = "manage/getBuildNotContactHouse", method = RequestMethod.POST)
    @ResponseBody
    public Object getBuildNotContactHouse(String userId, String projectId) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            userId = request.getAttribute("userId") == null ? null : request.getAttribute("userId").toString();
            projectId = request.getAttribute("projectId") == null ? null : request.getAttribute("projectId").toString();
            //参数合法性判断
            if (StringUtils.isBlank(userId)) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_USERPROJECTSTATUS_NOT_NULL.getErrorCode());
            }
            if (StringUtils.isBlank(projectId)) {
                return new MessageVO(PropertyErrorCodeEnum.PUB_PROJECT_ID_EMPTY_ERR.getErrorCode());
            }
            //获取与用户绑定的楼栋下房间地址数量,Map<buildId, roomCount>:楼栋Id，楼栋下住户绑定的房间数量
            Map<String, Integer> contactCountMap = iPropertyHouseHoldInfoServiceClient.getBuildNotContactHouse(userId, projectId);
            //获取当前小区的楼栋信息以及楼栋下所有房间数量
            PropertyProjectGetBuildSimpleInfoDTO propertyProjectGetBuildSimpleInfoDTO = new PropertyProjectGetBuildSimpleInfoDTO();
            propertyProjectGetBuildSimpleInfoDTO.setProjectId(projectId);
            propertyProjectGetBuildSimpleInfoDTO.setStatus(DataStatusEnum.NORMAL.getType());
            propertyProjectGetBuildSimpleInfoDTO.setPageSize(String.valueOf(PlatformConstants.MAX_BUILD_NUM));
            Page<PropertyProjectBuildSimpleInfoExVO> page =
                    iPropertyBuildInfoServiceClient.getPageBuildSimpleInfoExList(propertyProjectGetBuildSimpleInfoDTO);
            if ((page == null) || (page.getRows().size() < 1)) {
                return new MessageVO(PropertyErrorCodeEnum.PROJECT_BUILD_INFO_NOT_EXISTS_ERR.getErrorCode());
            }
            //整理去掉所有房间与住户完全绑定的楼栋的信息
            List<PropertyProjectBuildSimpleInfoExVO> propertyProjectBuildSimpleInfoExVOS = page.getRows();
            List<PropertyProjectBuildSimpleInfoExVO> propertyProjectBuildSimpleInfoExVOList = new ArrayList<>();
            for (PropertyProjectBuildSimpleInfoExVO propertyProjectBuildSimpleInfoExVO : propertyProjectBuildSimpleInfoExVOS) {
                String buildId = propertyProjectBuildSimpleInfoExVO.getBuildId();
                //楼栋下房间的数量
                Integer roomCount = propertyProjectBuildSimpleInfoExVO.getRoomCount();
                //住户在指定楼栋下所绑定房间的数量
                Integer roomCountContractHouse = contactCountMap.get(buildId);
                if ((roomCountContractHouse == null) || (roomCount != roomCountContractHouse)) {
                    propertyProjectBuildSimpleInfoExVOList.add(propertyProjectBuildSimpleInfoExVO);
                }
            }
            page.setRows(propertyProjectBuildSimpleInfoExVOList, propertyProjectBuildSimpleInfoExVOList.size());
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), page);
        } catch (Exception e) {
            throw new DataAccessException(String.format(
                    "【物业系统_住户信息管理_获取未与用户完全绑定的楼栋地址】获取未与用户完全绑定的楼栋地址失败"), e);
        }
    }

    /**
     * <desc>
     * 获取未与用户完全绑定的单元地址(获取不是所有房屋都与住户绑定的单元地址)
     * <desc/>
     *
     * @param userId    住户Id
     * @param projectId 项目Id
     * @param buildId   楼栋Id
     * @return MessageVO 标准格式化响应结果
     * @author zhangs
     * @createDate 2017/11/10
     */
    @RequestMapping(path = "manage/getUnitNotContactHouse", method = RequestMethod.POST)
    @ResponseBody
    public Object getBuildNotContactHouse(
            String userId,
            String projectId,
            String buildId) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            userId = request.getAttribute("userId") == null ? null : request.getAttribute("userId").toString();
            projectId = request.getAttribute("projectId") == null ? null : request.getAttribute("projectId").toString();
            buildId = request.getAttribute("buildId") == null ? null : request.getAttribute("buildId").toString();
            //参数合法性判断
            if (StringUtils.isBlank(userId)) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_USERPROJECTSTATUS_NOT_NULL.getErrorCode());
            }
            if (StringUtils.isBlank(projectId)) {
                return new MessageVO(PropertyErrorCodeEnum.PUB_PROJECT_ID_EMPTY_ERR.getErrorCode());
            }
            if (StringUtils.isBlank(buildId)) {
                return new MessageVO(PropertyErrorCodeEnum.PROJECT_BUILD_ID_EMPTY_ERR.getErrorCode());
            }
            //获取与用户绑定的指定楼栋的单元下房间地址数量,Map<unitId, roomCount>:单元Id，单元下住户绑定的房间数量
            Map<String, Integer> contactCountMap =
                    iPropertyHouseHoldInfoServiceClient.getUnitNotContactHouse(userId, projectId, buildId);
            //获取当前小区指定楼栋的单元信息以及单元下所有房间数量
            PropertyProjectGetUnitSimpleInfoDTO propertyProjectGetUnitSimpleInfoDTO = new PropertyProjectGetUnitSimpleInfoDTO();
            propertyProjectGetUnitSimpleInfoDTO.setBuildId(buildId);
            propertyProjectGetUnitSimpleInfoDTO.setStatus(DataStatusEnum.NORMAL.getType());
            propertyProjectGetUnitSimpleInfoDTO.setPageSize(String.valueOf(PlatformConstants.MAX_UNIT_NUM));
            Page<PropertyProjectUnitSimpleInfoExVO> page =
                    iPropertyUnitInfoServiceClient.getPageUnitSimpleInfoExList(propertyProjectGetUnitSimpleInfoDTO);
            if ((page == null) || (page.getRows().size() < 1)) {
                return new MessageVO(PropertyErrorCodeEnum.PROJECT_UNIT_INFO_NOT_EXISTS_ERR.getErrorCode());
            }
            //整理去掉所有房间与住户完全绑定的单元的信息
            List<PropertyProjectUnitSimpleInfoExVO> propertyProjectUnitSimpleInfoExVOS = page.getRows();
            List<PropertyProjectUnitSimpleInfoExVO> propertyProjectUnitSimpleInfoExVOList = new ArrayList<>();
            for (PropertyProjectUnitSimpleInfoExVO propertyProjectUnitSimpleInfoExVO : propertyProjectUnitSimpleInfoExVOS) {
                String unitId = propertyProjectUnitSimpleInfoExVO.getUnitId();
                Integer roomCount = propertyProjectUnitSimpleInfoExVO.getRoomCount();
                Integer roomCountContractHouse = contactCountMap.get(unitId);
                if ((roomCountContractHouse == null) || (roomCount != roomCountContractHouse)) {
                    propertyProjectUnitSimpleInfoExVOList.add(propertyProjectUnitSimpleInfoExVO);
                }
            }
            page.setRows(propertyProjectUnitSimpleInfoExVOList, propertyProjectUnitSimpleInfoExVOList.size());
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), page);
        } catch (Exception e) {
            throw new DataAccessException(String.format("【物业系统_住户信息管理_获取未与用户完全绑定的单元地址】" +
                    "获取未与用户完全绑定的单元地址失败"), e);
        }
    }

    /**
     * <desc>
     * 房屋管理-房屋详情-入住迁出记录
     * <desc/>
     *
     * @param checkHouseHoldByRoomDTO 房屋详情中查询入住迁出记录条件数据传输对象
     * @return MessageVO 标准格式化响应结果
     * @author zhangs
     * @createDate 2017/11/23
     */
    @RequestMapping(path = "/manage/moveInAndOutRecord", method = RequestMethod.POST)
    @ResponseBody
    public Object moveInAndOutRecord(CheckHouseHoldByRoomDTO checkHouseHoldByRoomDTO) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            checkHouseHoldByRoomDTO = HttpProtocolUtil.parseRequestParamToDTO(CheckHouseHoldByRoomDTO.class, request);
            if (checkHouseHoldByRoomDTO == null) {
                return new MessageVO(PropertyErrorCodeEnum.PROJECT_ROOM_INFO_NOT_NULL.getErrorCode());
            }
            String roomId = checkHouseHoldByRoomDTO.getRoomId();
            String roomNum = checkHouseHoldByRoomDTO.getRoomNum();
            if (StringUtils.isBlank(roomId)) {
                return new MessageVO(PropertyErrorCodeEnum.PROJECT_ROOM_ID_EMPTY_ERR.getErrorCode());
            }
            if (StringUtils.isBlank(checkHouseHoldByRoomDTO.getProjectId())) {
                return new MessageVO(PropertyErrorCodeEnum.PUB_PROJECT_ID_EMPTY_ERR.getErrorCode());
            }

            List<CheckHouseHoldByRoomVO> checkHouseHoldByRoomVOS =
                    iPropertyHouseHoldInfoServiceClient.moveInAndOutRecord(checkHouseHoldByRoomDTO);
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), checkHouseHoldByRoomVOS);
        } catch (Exception e) {
            throw new DataAccessException(String.format(
                    "【物业系统_住户信息管理_查询住户信息】查询住户信息失败"), e);
        }
    }

    /**
     * <desc>
     * 地址变更更新App端用户的设备权限
     * <desc/>
     *
     * @param userId     二级用户Id
     * @param authUserId 一级用户Id
     * @param projectId  项目Id
     * @return
     * @author zhangs
     * @createDate 2017/10/20
     */
    @RequestMapping(path = "/manage/updateAppUserAuth", method = RequestMethod.POST)
    @LoggerInfo(operateDesc = LogDescConstant.APP_ADDRESS_CHANGE_USER_DEVICE_AUTH_LOG_DESC)
    @ResponseBody
    public Object updateAppUserAuth(
            String userId,
            String authUserId,
            String projectId) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            userId = request.getAttribute("userId") == null ? null : request.getAttribute("userId").toString();
            projectId = request.getAttribute("projectId") == null ? null : request.getAttribute("projectId").toString();
            authUserId = request.getAttribute("authUserId") == null ? null : request.getAttribute("authUserId").toString();
            List<String> userIds = new ArrayList<>();
            userIds.add(userId);
            iPropertyHouseHoldInfoServiceClient.updateAppUserAuth(userIds, authUserId, projectId);
            return new MessageVO(userId, BaseErrorCodeEnum.SUCCESS.getErrorCode());
        } catch (Exception e) {
            throw new DataAccessException(e);
        }
    }

    /**
     * <desc>
     * 临时提供一个通过手机号码查询APP用户id接口
     * </desc>
     *
     * @param phoneNum
     * @return
     * @author wangzhi
     * @createDate 2018-04-18
     */
    @RequestMapping(path = "/manage/getAppUserId")
    @ResponseBody
    public Object getAppUserIdTemporary(String phoneNum) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            phoneNum = request.getAttribute("phoneNum") == null ? null : request.getAttribute("phoneNum").toString();
            if (StringUtils.isBlank(phoneNum)) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            String userId = iPropertyHouseHoldInfoServiceClient.getAppUserIdTemporary(phoneNum);
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), "成功", userId);
        } catch (Exception e) {
            throw new DataAccessException("【获取app用户id失败】", e);
        }
    }

    /**
     * <desc>
     * 创建百度人脸
     * </desc>
     *
     * @param operateCreateBaiduFaceDTO 人脸创建信息
     * @return
     * @author Qiang.S
     * @createDate 2018-05-18
     */
    public Object createBaiduFace(PropertyUserProofAuthDTO operateCreateBaiduFaceDTO) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            operateCreateBaiduFaceDTO = HttpProtocolUtil.parseRequestParamToDTO(PropertyUserProofAuthDTO.class, request);
            if (operateCreateBaiduFaceDTO == null) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_CREATEBAIDUFACE_NOT_NULL.getErrorCode());
            }
            if (StringUtils.isBlank(operateCreateBaiduFaceDTO.getProjectId())) {
                return new MessageVO(PropertyErrorCodeEnum.PUB_PROJECT_ID_EMPTY_ERR.getErrorCode());
            }
            if (StringUtils.isBlank(operateCreateBaiduFaceDTO.getUserId())) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_USERID_NOT_NULL.getErrorCode());
            }
            if (StringUtils.isBlank(operateCreateBaiduFaceDTO.getPhoneNo())) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_PHONENUM_NOT_NULL.getErrorCode());
            }
            if (StringUtils.isBlank(operateCreateBaiduFaceDTO.getImageStr())) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_IMAGETER_NOT_NULL.getErrorCode());
            }
            if (StringUtils.isBlank(operateCreateBaiduFaceDTO.getImageType())) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_IMAGETYPE_NOT_NULL.getErrorCode());
            }
            //判断项目是否开启人脸识别,并查询是否有百度库key
            OperateFaceApplyInfoVO operateFaceApplyInfoVO = iOperateFaceApplyServiceClient.getFaceByProjectId(operateCreateBaiduFaceDTO.getProjectId());
            if (operateFaceApplyInfoVO == null) {
                ErrorCode errorCode = AppErrorCodeEnum.PROJECT_FACE_APPID_INEXISTENCE.getErrorCode();
                return new MessageVO(errorCode);
            }
            //判断图片是否合格
            String[] imageStrS = operateCreateBaiduFaceDTO.getImageStr().split(",");
            operateCreateBaiduFaceDTO.setImageStr(imageStrS[1]);
            AppCreateBaiduFaceVO appCreateBaiduFaceVO = new AppCreateBaiduFaceVO();
            appCreateBaiduFaceVO.setAPP_ID(operateFaceApplyInfoVO.getAppId());
            appCreateBaiduFaceVO.setAPI_KEY(operateFaceApplyInfoVO.getApiKey());
            appCreateBaiduFaceVO.setSECRET_KEY(operateFaceApplyInfoVO.getSecretKey());
            appCreateBaiduFaceVO.setFaceScore(operateFaceApplyInfoVO.getFaceScore() == 0F ? 80F : operateFaceApplyInfoVO.getFaceScore());
//            appCreateBaiduFaceVO.setFile(new BASE64Decoder().decodeBuffer(operateCreateBaiduFaceDTO.getImageStr()));
            //保存图片
            String uploadFilePath = uploadImageFile(new BASE64Decoder().decodeBuffer(operateCreateBaiduFaceDTO.getImageStr()), operateCreateBaiduFaceDTO.getImageType(), FileCatalogEnum.BAIDU_FACE_CREATE_FILE);
            appCreateBaiduFaceVO.setImageUrl(uploadFilePath);
            appCreateBaiduFaceVO.setUid(operateCreateBaiduFaceDTO.getUserId());
            String checkResult = iIotBaiduFaceServiceClient.faceVerify(appCreateBaiduFaceVO);
            if (checkResult != null && !"".equals(checkResult)) {
                if ("error".equals(checkResult)) {//调用接口异常
                    return new MessageVO(PropertyErrorCodeEnum.APPUSER_FACEVERFY_ERROR.getErrorCode());
                }
                if ("busy".equals(checkResult)) {//调用接口忙
                    return new MessageVO(PropertyErrorCodeEnum.APPUSER_BAIDU_BUSY.getErrorCode());
                }
                if ("others".equals(checkResult)) {//图片不合格,非真人图片
                    return new MessageVO(PropertyErrorCodeEnum.APPUSER_BAIDU_PICTURE_ERROR.getErrorCode());
                }
                if ("result_num".equals(checkResult)) {//人脸数异常
                    return new MessageVO(PropertyErrorCodeEnum.APPUSER_FACE_RESULTNUM_NOT_1.getErrorCode());
                }
                if ("size".equals(checkResult)) {//人脸太小
                    return new MessageVO(PropertyErrorCodeEnum.APPUSER_FACE_SIZE_TOO_SMALL.getErrorCode());
                }
                //2020年8月5号 按照需求说明取消活体检测
             /*   if ("faceliveness".equals(checkResult)) {//活体值异常
                    return new MessageVO(PropertyErrorCodeEnum.APPUSER_FACE_FACELIVENESS_TOO_LOW.getErrorCode());
                }*/
                if ("left_eye".equals(checkResult) || "right_eye".equals(checkResult) || "nose".equals(checkResult)
                        || "mouth".equals(checkResult) || "left_cheek".equals(checkResult) || "right_cheek".equals(checkResult)
                        || "chin".equals(checkResult)) {//图片遮挡
                    return new MessageVO(PropertyErrorCodeEnum.APPUSER_FACE_OCCLUSION.getErrorCode());
                }
                if ("blur".equals(checkResult)) {//模糊
                    return new MessageVO(PropertyErrorCodeEnum.APPUSER_FACE_BLUR_TOO_LOW.getErrorCode());
                }
                if ("illumination_min".equals(checkResult)) {//光照过暗
                    return new MessageVO(PropertyErrorCodeEnum.APPUSER_FACE_ILLUMINATION_TOO_LOW.getErrorCode());
                }
                if ("illumination_max".equals(checkResult)) {//光照过亮
                    return new MessageVO(PropertyErrorCodeEnum.APPUSER_FACE_ILLUMINATION_TOO_HIGH.getErrorCode());
                }
                if ("pitch".equals(checkResult) || "roll".equals(checkResult) || "yaw".equals(checkResult)) {//角度
                    return new MessageVO(PropertyErrorCodeEnum.APPUSER_FACE_ANGLE_NOT_STRAIGHT.getErrorCode());
                }
                if ("completeness".equals(checkResult)) {//人脸完整度
                    return new MessageVO(PropertyErrorCodeEnum.APPUSER_FACE_COMPLETENESS_IMPERFECT.getErrorCode());
                }
            }
            //  2020年8月5号 按照需求说明取消人脸重复比对检测
            //判断认证图片是否重复
           /* String repeatResult = iIotBaiduFaceServiceClient.identifyUser(appCreateBaiduFaceVO);
            if (repeatResult != null && !"".equals(repeatResult)) {
                if ("error".equals(repeatResult)) {//调用接口异常
                    return new MessageVO(PropertyErrorCodeEnum.APPUSER_IDENTIFY_ERROR.getErrorCode());
                }
                if ("busy".equals(repeatResult)) {//调用接口忙
                    return new MessageVO(PropertyErrorCodeEnum.APPUSER_BAIDU_BUSY.getErrorCode());
                }
                if ("face_repeat".equals(repeatResult)) {//人脸重复注册
                    return new MessageVO(PropertyErrorCodeEnum.APPUSER_CREATE_FACE_REPEAT.getErrorCode());
                }
            }*/

            //保存数据
            AppUserProjectPO appUserProjectPO = new AppUserProjectPO();
            appUserProjectPO.setUserId(operateCreateBaiduFaceDTO.getUserId());
            appUserProjectPO.setProjectId(operateCreateBaiduFaceDTO.getProjectId());
            appUserProjectPO.setFacePicUrl(uploadFilePath);
            appUserProjectPO.setFaceCreateTime(new Date());
            appUserProjectPO.setUpdateTime(new Date());
            appUserProjectPO.setIsFace(2);//认证中
            int updateNumber = iPropertyHouseHoldInfoServiceClient.updatePreUserBaiduFaceInfo(appUserProjectPO);
            if (updateNumber == 0) {
                return new MessageVO(BaseErrorCodeEnum.ERROR.getErrorCode(), null);
            }

            //添加人脸注册信息到队列
            appCreateBaiduFaceVO.setProjectId(operateCreateBaiduFaceDTO.getProjectId());
            appCreateBaiduFaceVO.setUserPhone(operateCreateBaiduFaceDTO.getPhoneNo());
            appCreateBaiduFaceVO.setUid(operateCreateBaiduFaceDTO.getUserId());
            appCreateBaiduFaceVO.setUserName(operateCreateBaiduFaceDTO.getUserName());
            appCreateBaiduFaceVO.setUserInfo(operateCreateBaiduFaceDTO.getUserName());//userInfo使用用户名
            appCreateBaiduFaceVO.setUploadFilePath(uploadFilePath);
            boolean result = iIotBaiduFaceServiceClient.createBaiduFace(appCreateBaiduFaceVO);
            if (!result) {
                return new MessageVO(BaseErrorCodeEnum.ERROR.getErrorCode(), result);
            }
            //查询当前项目信息
            ProjectPO projectPO = iOperateProjectServiceClient.getOneProject(operateCreateBaiduFaceDTO.getProjectId());
            // 平板优先离线，则插入同步数据
            if (projectPO.getOnOffLinePadFace() != null) {
                PadFaceSyncDataDTO padFaceSyncDataDTO = new PadFaceSyncDataDTO();
                padFaceSyncDataDTO.setOperateType("1");
                padFaceSyncDataDTO.setAppUserIds(operateCreateBaiduFaceDTO.getUserId());
                padFaceSyncDataDTO.setProjectId(operateCreateBaiduFaceDTO.getProjectId());
                padFaceSyncDataDTO.setStatus("1");
                padFaceSyncDataDTO.setSourceSystem(2);
                if (projectPO.getOnOffLinePadFace() == 1) {
                    iPadFaceSyncDataServiceClient.userOrFloorSync(padFaceSyncDataDTO);
                }
                iPadFaceSyncDataServiceClient.userOrFloorSyncSmartCard(padFaceSyncDataDTO);
            }

        } catch (Exception e) {
            throw new DataAccessException(String.format(
                    "【物业系统_住户信息管理_人脸注册】人脸注册申请失败"), e);
        }
        return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode());
    }

    /**
     * <desc>
     * 判断当前项目是否可以注册人脸
     * </desc>
     *
     * @param projectId 项目编号
     * @return
     * @author Qiang.S
     * @createDate 2018-05-18
     */
    @RequestMapping(path = "/manage/getCanRegisterFace")
    @ResponseBody
    public Object getCanRegisterFace(String projectId) {
        int canRegister = 0;
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            projectId = request.getAttribute("projectId") == null ? null : request.getAttribute("projectId").toString();
            if (StringUtils.isBlank(projectId)) {
                return new MessageVO(PropertyErrorCodeEnum.PUB_PROJECT_ID_EMPTY_ERR.getErrorCode());
            }
            //判断项目是否开启人脸识别,并查询是否有百度库key
            OperateFaceApplyInfoVO operateFaceApplyInfoVO = iOperateFaceApplyServiceClient.getFaceByProjectId(projectId);
            if (operateFaceApplyInfoVO != null) {
                canRegister = 1;
            }
        } catch (Exception e) {
            throw new DataAccessException(String.format(
                    "【物业系统_住户信息管理_是否可以人脸注册查询】人脸注册权限查询失败"), e);
        }
        return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), canRegister);
    }

    /**
     * <desc>
     * 查询人脸注册信息
     * </desc>
     *
     * @param projectId 项目编号
     * @param userId    用户编号
     * @return
     * @author Qiang.S
     * @createDate 2018-05-18
     */
    @RequestMapping(path = "/manage/getCreateBaiduFaceInfo")
    @ResponseBody
    @AuthAccessRequired
    public Object getCreateBaiduFaceInfo(String projectId, String userId) {
        AppUserFaceVO appUserFaceVO;
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            userId = request.getAttribute("userId") == null ? null : request.getAttribute("userId").toString();
            projectId = request.getAttribute("projectId") == null ? null : request.getAttribute("projectId").toString();
            if (StringUtils.isBlank(projectId)) {
                return new MessageVO(PropertyErrorCodeEnum.PUB_PROJECT_ID_EMPTY_ERR.getErrorCode());
            }
            if (StringUtils.isBlank(userId)) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_USERID_NOT_NULL.getErrorCode());
            }
            appUserFaceVO = iAppMineServiceClient.getCreateBaiduFaceInfo(userId, projectId);
        } catch (Exception e) {
            throw new DataAccessException(String.format(
                    "【物业系统_住户信息管理_人脸注册信息查询】人脸注册信息查询失败"), e);
        }
        return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), appUserFaceVO);
    }

    /**
     * <desc>
     * 将用户和身份证序号绑定
     * </desc>
     *
     * @param projectId 项目编号
     * @param userId    用户编号
     * @param idcardKey 身份证序号
     * @param idCard    身份证号
     * @return
     * @author Qiang.S
     * @createDate 2018-08-22
     */
    public Object bindingIDCard(String projectId, String userId,
                                String idcardKey, String idCard) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            userId = request.getAttribute("userId") == null ? null : request.getAttribute("userId").toString();
            projectId = request.getAttribute("projectId") == null ? null : request.getAttribute("projectId").toString();
            idcardKey = request.getAttribute("idcardKey") == null ? null : request.getAttribute("idcardKey").toString();
            idCard = request.getAttribute("idCard") == null ? "" : request.getAttribute("idCard").toString();
            if (StringUtils.isBlank(projectId)) {
                return new MessageVO(PropertyErrorCodeEnum.PUB_PROJECT_ID_EMPTY_ERR.getErrorCode());
            }
            if (StringUtils.isBlank(userId)) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_USERID_NOT_NULL.getErrorCode());
            }
            if (StringUtils.isBlank(idcardKey)) {
                return new MessageVO(PropertyErrorCodeEnum.PROJECT_CARD_KEY_EMPTY_ERR.getErrorCode());
            }
            if (idCard != null && !"".equals(idCard)) {
                idCard = UserTokenUtil.getPassword(idCard, userTokenKey);
            }
            //判断此身份证是否已经被绑定
            if (iPropertyHouseHoldInfoServiceClient.getIDCardByUserId(userId, projectId, idcardKey) > 0) {
                return new MessageVO(PropertyErrorCodeEnum.PROJECT_IDCARD_KEY_IS_BINDING_ERR.getErrorCode());
            }
            if (iPropertyHouseHoldInfoServiceClient.bindingIDCard(userId, projectId, idcardKey, idCard,"",false) >= 0) {
                return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode());
            }
            return new MessageVO(userId, BaseErrorCodeEnum.ERROR.getErrorCode());
        } catch (Exception e) {
            throw new DataAccessException(String.format(
                    "【物业系统_住户信息管理_身份证绑定】身份证绑定失败"), e);
        }
    }

    /**
     * <desc>
     * 用户身份证解绑
     * </desc>
     *
     * @param projectId 项目编号
     * @param userId    用户编号
     * @return
     * @author Qiang.S
     * @createDate 2018-08-22
     */
    @RequestMapping(path = "/manage/untieIDCard")
    @ResponseBody
    @LoggerInfo(operateDesc = LogDescConstant.UNBAND_USER_ID_CARD_LOG_DESC)
    @AuthAccessRequired
    public Object untieIDCard(String projectId, String userId) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            userId = request.getAttribute("userId") == null ? null : request.getAttribute("userId").toString();
            projectId = request.getAttribute("projectId") == null ? null : request.getAttribute("projectId").toString();
            if (StringUtils.isBlank(projectId)) {
                return new MessageVO(PropertyErrorCodeEnum.PUB_PROJECT_ID_EMPTY_ERR.getErrorCode());
            }
            if (StringUtils.isBlank(userId)) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_USERID_NOT_NULL.getErrorCode());
            }
            if (iPropertyHouseHoldInfoServiceClient.untieIDCard(userId, projectId) >= 0) {
                return new MessageVO(userId, BaseErrorCodeEnum.SUCCESS.getErrorCode());
            }
            return new MessageVO(BaseErrorCodeEnum.ERROR.getErrorCode());
        } catch (Exception e) {
            throw new DataAccessException(String.format(
                    "【物业系统_住户信息管理_身份证解绑】身份证解绑失败"), e);
        }
    }

    /**
     * <desc>
     * 身份证挂失
     * </desc>
     *
     * @param projectId 项目编号
     * @param userId    用户编号
     * @return
     * @author Qiang.S
     * @createDate 2019-02-20
     */
    @RequestMapping(path = "/manage/reportLost")
    @ResponseBody
    @LoggerInfo(operateDesc = LogDescConstant.USER_ID_CARD_REPORT_LOSS_LOG_DESC)
    @AuthAccessRequired
    public Object reportLost(String projectId, String userId) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            userId = request.getAttribute("userId") == null ? null : request.getAttribute("userId").toString();
            projectId = request.getAttribute("projectId") == null ? null : request.getAttribute("projectId").toString();
            if (StringUtils.isBlank(projectId)) {
                return new MessageVO(PropertyErrorCodeEnum.PUB_PROJECT_ID_EMPTY_ERR.getErrorCode());
            }
            if (StringUtils.isBlank(userId)) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_USERID_NOT_NULL.getErrorCode());
            }
            if (iPropertyHouseHoldInfoServiceClient.updateIsLossInfo(userId, projectId, "1") >= 0) {
                return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode());
            }
            return new MessageVO(BaseErrorCodeEnum.ERROR.getErrorCode());
        } catch (Exception e) {
            throw new DataAccessException(String.format(
                    "【物业系统_住户信息管理_身份证挂失】身份证挂失失败"), e);
        }
    }

    /**
     * <desc>
     * 身份证解挂
     * </desc>
     *
     * @param projectId 项目编号
     * @param userId    用户编号
     * @return
     * @author Qiang.S
     * @createDate 2019-02-20
     */
    @RequestMapping(path = "/manage/reportUnlost")
    @ResponseBody
    @LoggerInfo(operateDesc = LogDescConstant.USER_ID_CARD_REPORT_UN_LOSS_LOG_DESC)
    @AuthAccessRequired
    public Object reportUnlost(String projectId, String userId) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            userId = request.getAttribute("userId") == null ? null : request.getAttribute("userId").toString();
            projectId = request.getAttribute("projectId") == null ? null : request.getAttribute("projectId").toString();
            if (StringUtils.isBlank(projectId)) {
                return new MessageVO(PropertyErrorCodeEnum.PUB_PROJECT_ID_EMPTY_ERR.getErrorCode());
            }
            if (StringUtils.isBlank(userId)) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_USERID_NOT_NULL.getErrorCode());
            }
            if (iPropertyHouseHoldInfoServiceClient.updateIsLossInfo(userId, projectId, "0") >= 0) {
                return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode());
            }
            return new MessageVO(BaseErrorCodeEnum.ERROR.getErrorCode());
        } catch (Exception e) {
            throw new DataAccessException(String.format(
                    "【物业系统_住户信息管理_身份证解除挂失】身份证解除挂失失败"), e);
        }
    }

    /**
     * <desc>
     *      注销用户人脸
     * </desc>
     *
     * @return
     * @Author Zhu.yj
     * @createDate  2021/4/17
     */
    @PostMapping("/logoffUserFace")
    public Object logoffUserFace(HttpServletRequest request){
        try{
            String projectId = request.getAttribute("projectId") == null ? null : request.getAttribute("projectId").toString();
            String userId = request.getAttribute("userId") == null ? null : request.getAttribute("userId").toString();

            if (StringUtils.isBlank(projectId) || StringUtils.isBlank(userId)){
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            new Thread(() ->{
                try {
                    //清除人脸以及ftp照片
                    iIotVisitorFaceServiceClient.deleteJdUserFace(userId, projectId);
                    //处理平板指令
                    iPadFaceSyncDataServiceClient.jdUserSyncForSDK(userId, projectId);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }).start();
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode());
        }catch (Exception e){
            throw new DataAccessException("【物业系统_住户管理_注销人脸】注销人脸失败", e);
        }
    }

    /**
     * <desc>
     *      根据项目id获取项目下的角色组
     * </desc>
     *
     * @param projectId 项目id
     * @return
     * @Author Zhu.yj
     * @createDate  2021/4/19
     */
    @PostMapping("/getUserRoleList")
    public Object getUserTypeByProjectId(String projectId, HttpServletRequest request){
        try {
            projectId = request.getAttribute("projectId") == null ? null : request.getAttribute("projectId").toString();
            if(StringUtils.isBlank(projectId)){
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            List<Map<String, Object>> userRoleList = iOperateProjectServiceClient.getUserRoleList(projectId);
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), userRoleList);
        }catch (Exception e){
            throw new DataAccessException("【物业系统_住户管理】获取项目下的角色组列表失败", e);
        }
    }

    /**
     * <desc>
     *      获取项目下楼栋单元房间列表
     * </desc>
     *
     * @param
     * @return
     * @Author Zhu.yj
     * @createDate  2021/4/19
     */
    @PostMapping("getBuildList")
    public Object getBuildList(String projectId, HttpServletRequest request){
        try{
            projectId = request.getAttribute("projectId") == null ? null : request.getAttribute("projectId").toString();
            if(StringUtils.isBlank(projectId)){
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            List<PropertyTreeMenuVO> propertyTreeMenuVOS = iOperateProjectServiceClient.getBuildList(projectId);
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), propertyTreeMenuVOS);
        }catch(Exception e){
            throw new DataAccessException("【物业系统_住户管理】获取项目下楼栋单元房间列表失败", e);
        }
    }

    /**
     * <desc>
     *      获取项目下的用户类型
     * </desc>
     *
     * @param
     * @return
     * @Author Zhu.yj
     * @createDate  2021/4/20
     */
    @PostMapping("getUserTypeList")
    public Object getUserTypeList(String projectId, HttpServletRequest request){
        try {
            projectId = request.getAttribute("projectId") == null ? null : request.getAttribute("projectId").toString();
            if (StringUtils.isBlank(projectId)){
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }

            List<Map<String, Object>> userTypeList = iAppProjectServiceClient.getProjectRoleListByProjectId(projectId);
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), userTypeList);
        }catch (Exception e){
            throw new DataAccessException("【物业系统_住户管理】获取项目下用户类型列表失败", e);
        }
    }

    /**
     * <desc>
     *      获取用户有权限的设备分页列表
     * </desc>
     *
     * @param
     * @return
     * @Author Zhu.yj
     * @createDate  2021/4/21
     */
    @PostMapping("getUserHaveAuthDevice")
    public Object getUserHaveAuthDevice(HttpServletRequest request){
        try{
            PropertyEquipAuthGetDTO  propertyEquipAuthGetDTO = HttpProtocolUtil.parseRequestParamToDTO(PropertyEquipAuthGetDTO.class, request);

            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode());
        }catch (Exception e){
            throw new DataAccessException("【物业系统_住户管理】获取用户有权限的设备分页列表失败", e);
        }
    }

    /**
     * <desc>
     *      分解前端传入的地址权限和分组权限,并返回分组权限
     * </desc>
     *
     * @param appUserRoomDTOS 地址信息列表 处理后赋值
     * @return roleIdList 角色组id列表
     * @Author Zhu.yj
     * @createDate  2021/4/19
     */
    private List<String> divideAddressAndRoleAuth( List<AppUserRoomDTO> appUserRoomDTOS, AppUserGetUserInfoDTO appUserGetUserInfoDTO) throws Exception{

        List<String> roleIdList = new ArrayList<>();
        List<AppUserRoomAndRoleInfoDTO> appUserRoomAndRoleInfoDTOS = JSONArray.parseArray(appUserGetUserInfoDTO.getAuthInfo(), AppUserRoomAndRoleInfoDTO.class);
        LOG.info(appUserGetUserInfoDTO.getAuthInfo());
        for (AppUserRoomAndRoleInfoDTO roomAndRoleInfoDTO : appUserRoomAndRoleInfoDTOS) {
            //房屋授权
            if ("1".equals(roomAndRoleInfoDTO.getAuthType())) {
                AppUserRoomDTO userRoomDTO = new AppUserRoomDTO();
                List<String> singleAddress = roomAndRoleInfoDTO.getAddressList();
                userRoomDTO.setBuildId(singleAddress.get(0));
                userRoomDTO.setUnitId(singleAddress.get(1));
                userRoomDTO.setRoomId(singleAddress.get(2));

                //目前若要沿用之前的逻辑的话需要传入roomNum，但需求变更之后前端无法传入roomNum
                String roomNum = iPropertyHouseHoldInfoServiceClient.getRoomNum(userRoomDTO.getRoomId());
                userRoomDTO.setRoomNum(roomNum);
                userRoomDTO.setHouserType(Integer.valueOf(roomAndRoleInfoDTO.getHouseType()));
                appUserRoomDTOS.add(userRoomDTO);
            }
            if ("2".equals(roomAndRoleInfoDTO.getAuthType())){
                roleIdList = roomAndRoleInfoDTO.getRoleIdList();
            }
        }
        return roleIdList;
    }

    /**
     * <desc>
     *      用户角色组设备授权
     * </desc>
     *
     * @param roleIdList 用户角色组id列表
     * @param projectId 项目id
     * @param userId 用户id
     * @param loginUserId 操作人id
     * @return
     * @Author Zhu.yj
     * @createDate  2021/4/12
     */
    private void userDeviceAuth(List<String> roleIdList, String projectId, String userId, String loginUserId) throws Exception{
        List<Map<String,Object>> list = new ArrayList<>();
        //获取用户的临时权限数据
        Map<String, Object> tempAuthMap = iPropertyHouseHoldInfoServiceClient.getOldUserTempAuth(userId,projectId);
        list.add(tempAuthMap);

        //用户角色组授权
        PropertyHouseholdRoleAuthDTO propertyHouseholdRoleAuthDTO = new PropertyHouseholdRoleAuthDTO();
            propertyHouseholdRoleAuthDTO.setRoleId(String.join(",", roleIdList));
            propertyHouseholdRoleAuthDTO.setProjectId(projectId);
            propertyHouseholdRoleAuthDTO.setUserIds(userId);
        iPropertyHouseholdRoleServiceClient.userRoleGroupAuth(propertyHouseholdRoleAuthDTO);

        //门禁授权
        String currentDevices = iPropertyHouseholdRoleServiceClient.getAllDeviceUniqueStr(projectId);
        if (StringUtils.isBlank(currentDevices)) {
            currentDevices = "";
        }
        String deviceUniqueStrByRoleId = "";
        if(!roleIdList.isEmpty()){
            //找出当前选择的角色分组的所有门禁设备
            List<String> deviceUniqueListByRoleId = iPropertyHouseholdRoleServiceClient.getDeviceUniqueListByRoleId(String.join(",", roleIdList),"1");
            deviceUniqueStrByRoleId = deviceUniqueListByRoleId.toString().replace("[", "").replace("]", "").replaceAll(" ","");
        }
        iPropertyDeviceAuthServiceClient.updateHouseHoldTmpDeviceAuth(loginUserId, userId, projectId, 2
                , currentDevices, deviceUniqueStrByRoleId, new ArrayList<>(), "mark");



        //处理用户电梯设备权限表信息
        String deviceUniqueStrElevatorByRoleId = "";
        List<String> floorArr = new ArrayList<>();
        if (!roleIdList.isEmpty()){
            Map<String,Object> map = iPropertyHouseholdRoleServiceClient.getElevatorListByRoleId(String.join(",", roleIdList),"1");
            String allElevatorDevices = iPropertyHouseholdRoleServiceClient.getAllElevatorDeviceUniqueStr(projectId);
            if (StringUtils.isBlank(allElevatorDevices)) {
                allElevatorDevices = "";
            }
            if (map != null){
                List<String> deviceUniqueByElevatorArr = (List<String>) map.get("deviceUniqueArr");
                floorArr =(List<String>) map.get("floorArr");
                if (deviceUniqueByElevatorArr != null && !deviceUniqueByElevatorArr.isEmpty()){
                    deviceUniqueStrElevatorByRoleId = String.join(",", deviceUniqueByElevatorArr);
                }
            }
            if (floorArr == null){
                floorArr = new ArrayList<>();
            }
            iPropertyDeviceAuthServiceClient.updateHouseHoldTmpDeviceAuth(loginUserId, userId, projectId, 1
                    , allElevatorDevices, deviceUniqueStrElevatorByRoleId, floorArr, "mark");
        }else {
            //当角色组为空时，删除了用户所有的角色分组，此时删掉用户的分组设备权限
            iPropertyDeviceAuthServiceClient.deleteUserDeviceAuth(projectId, userId);
        }


        for(Map<String,Object> tempAuth : list) {
            //推送云门禁 云電梯分組权限数据
            iPropertyHouseHoldInfoServiceClient.pushTempUserInfos(projectId, tempAuth.get("userId").toString(), StringHandlerUtil.getNullOrStringForObject(tempAuth.get("doorAuth")),
                        StringHandlerUtil.getNullOrStringForObject(tempAuth.get("elevatorAuth")), StringHandlerUtil.getNullOrStringForObject(tempAuth.get("talkAuth")),"");
        }

    }

    /**
     * <desc>
     * 凭证授权添加
     * </desc>
     *
     * @param proofAuthDTO
     * @return
     * @author Juguang.S
     * @createDate 2021-04-20
     */
    @RequestMapping(path = "/manage/proofAuth")
    @ResponseBody
    @LoggerInfo(operateDesc = LogDescConstant.ADD_USER_PROOF_AUTH_LOG_DESC)
    public Object bindingIDCard(PropertyUserProofAuthDTO proofAuthDTO) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            proofAuthDTO = HttpProtocolUtil.parseRequestParamToDTO(PropertyUserProofAuthDTO.class, request);
            if (proofAuthDTO==null) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }

            PropertyUserProofAuthInfoGetVO authInfoGetVO = iPropertyHouseHoldInfoServiceClient.getUserFaceAndIdCardInfo(proofAuthDTO.getUserId(),proofAuthDTO.getProjectId());
            String idCard = proofAuthDTO.getIdCard();
            String newFaceImage = proofAuthDTO.getImageStr();
            String oldFaceUrl = authInfoGetVO.getFaceUrl();
            String newIdcardKey = proofAuthDTO.getIdcardKey();
            String oldIdcardKey = authInfoGetVO.getIdcardKey();
            String userId = proofAuthDTO.getUserId();
            String projectId = proofAuthDTO.getProjectId();
            String idCardStatus = proofAuthDTO.getIdCardStatus();
            if (StringUtils.isBlank(projectId)) {
                return new MessageVO(PropertyErrorCodeEnum.PUB_PROJECT_ID_EMPTY_ERR.getErrorCode());
            }
            if (StringUtils.isBlank(userId)) {
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_USERID_NOT_NULL.getErrorCode());
            }
            //处理绑定身份证相关逻辑 或重新绑定身份证相关逻辑
            if((StringUtils.isNotBlank(newIdcardKey) && StringUtils.isBlank(oldIdcardKey)) ||
                    (StringUtils.isNotBlank(newIdcardKey) && StringUtils.isNotBlank(oldIdcardKey) && !newIdcardKey.equals(oldIdcardKey))){
                boolean mark = false;
                if (idCard != null && !"".equals(idCard)) {
                    idCard = UserTokenUtil.getPassword(idCard, userTokenKey);
                }
                //判断此身份证是否已经被绑定
                if (iPropertyHouseHoldInfoServiceClient.getIDCardByUserId(userId, projectId, newIdcardKey) > 0) {
                    return new MessageVO(PropertyErrorCodeEnum.PROJECT_IDCARD_KEY_IS_BINDING_ERR.getErrorCode());
                }

                if((StringUtils.isNotBlank(newIdcardKey) && StringUtils.isNotBlank(oldIdcardKey) && !newIdcardKey.equals(oldIdcardKey))){
                    //处理解绑身份证相关逻辑
                    iPropertyHouseHoldInfoServiceClient.untieIDCard(userId, projectId);
                    mark = true;
                    //此处休眠是为了先解绑 并向设备推送解绑指令
                    Thread.sleep(2500);
                }
                iPropertyHouseHoldInfoServiceClient.bindingIDCard(userId, projectId, newIdcardKey, idCard,idCardStatus,mark);

            }else if(StringUtils.isBlank(newIdcardKey) && StringUtils.isNotBlank(oldIdcardKey) && StringUtils.isBlank(idCardStatus)){
                //处理解绑身份证相关逻辑
                iPropertyHouseHoldInfoServiceClient.untieIDCard(userId, projectId);
            }else if(StringUtils.isNotBlank(newIdcardKey) && StringUtils.isNotBlank(oldIdcardKey) && StringUtils.isNotBlank(idCardStatus) && "0".equals(idCardStatus)){
                //处理解挂 解冻相关逻辑
                iPropertyHouseHoldInfoServiceClient.updateIsLossInfo(userId, projectId, "0");
            }else if(StringUtils.isNotBlank(newIdcardKey) && StringUtils.isNotBlank(oldIdcardKey) && StringUtils.isNotBlank(idCardStatus) && "1".equals(idCardStatus)){
                //处理挂失 冻结相关逻辑
                iPropertyHouseHoldInfoServiceClient.updateIsLossInfo(userId, projectId, "1");
            }
            if(StringUtils.isNotBlank(proofAuthDTO.getFaceStatus()) && "1".equals(proofAuthDTO.getFaceStatus())){
                //此处处理人脸相关逻辑
                if(StringUtils.isBlank(newFaceImage) && StringUtils.isNotBlank(oldFaceUrl)){
                    //处理人脸注销相关逻辑
                    //清除人脸以及ftp照片
                    iIotVisitorFaceServiceClient.deleteJdUserFace(userId, projectId);
                    //处理平板指令
                    iPadFaceSyncDataServiceClient.userSyncForFaceUrl(userId, projectId);
                    //注销用户发送设备端指令
                    iAppMineServiceClient.logOffUserForProperty(userId,projectId);
                }else if(StringUtils.isNotBlank(newFaceImage)){
                    //处理人脸认证相关逻辑
                    return this.createBaiduFace(proofAuthDTO);
                }
            }
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode());
        } catch (Exception e) {
            throw new DataAccessException(String.format(
                    "【物业系统_住户信息管理_凭证授权添加】凭证授权添加失败"), e);
        }
    }



    /**
     * <desc>
     * 获取凭证授权详情
     * </desc>
     *
     * @param proofAuthDTO
     * @return
     * @author Juguang.S
     * @createDate 2021-04-20
     */
    @RequestMapping(path = "/manage/getProofAuthInfo")
    @ResponseBody
    public Object getProofAuthInfo(PropertyUserProofAuthDTO proofAuthDTO) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            proofAuthDTO = HttpProtocolUtil.parseRequestParamToDTO(PropertyUserProofAuthDTO.class, request);
            if (proofAuthDTO==null) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }

            PropertyUserProofAuthInfoGetVO authInfoGetVO = iPropertyHouseHoldInfoServiceClient.getUserFaceAndIdCardInfo(proofAuthDTO.getUserId(),proofAuthDTO.getProjectId());

            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(),authInfoGetVO);
        } catch (Exception e) {
            throw new DataAccessException(String.format(
                    "【物业系统_住户信息管理_获取凭证授权详情】获取凭证授权详情失败"), e);
        }
    }


    /**
     * <desc>
     *      获取用户有权限的设备列表
     * </desc>
     *
     * @param
     * @return
     * @Author Zhu.yj
     * @createDate  2021/4/26
     */
    @PostMapping("getUserDeviceInfo")
    public Object getUserDeviceInfo(HttpServletRequest request){
        try{
            PropertyEquipAuthGetDTO equipAuthGetDTO = HttpProtocolUtil.parseRequestParamToDTO(PropertyEquipAuthGetDTO.class, request);
            if(equipAuthGetDTO == null || equipAuthGetDTO.getDeviceType() == null
                    || StringUtils.isBlank(equipAuthGetDTO.getUserId()) || StringUtils.isBlank(equipAuthGetDTO.getProjectId())){
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            //获取用户设备权限
            Page<PropertyEquipSimpleVO> appUserGetDeviceAuthVOS =
                    iPropertyDeviceAuthServiceClient.getUserHaveAuthDevice(equipAuthGetDTO);

            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), appUserGetDeviceAuthVOS);
        }catch (Exception e){
            throw new DataAccessException("【物业系统_住户信息管理_getUserDeviceInfo】获取用户有权限的设备列表失败", e);
        }
    }

    /**
     * <desc>
     *   删除审批未通过的用户
     * </desc>
     *
     * @param
     * @return
     * @Author Zhu.yj
     * @createDate  2021/4/28
     */
    @PostMapping("removeUnPassedUser")
    public Object removeUnPassedUser(HttpServletRequest request, String projectId, String removeUsers){
        try {
            projectId = request.getAttribute("projectId") == null ? null : request.getAttribute("projectId").toString();
            removeUsers= request.getAttribute("removeUsers") == null ? null : request.getAttribute("removeUsers").toString();
            if (StringUtils.isBlank(projectId) || StringUtils.isBlank(removeUsers)){
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            List<AppUnCheckUserRemoveDTO> removeDTOList = new ArrayList<>();
            try {
                removeDTOList = JSONArray.parseArray(removeUsers, AppUnCheckUserRemoveDTO.class);
                if (removeDTOList.isEmpty()){
                    return new MessageVO(BaseErrorCodeEnum.PARAM_ERR.getErrorCode(), "用户信息不能为空");
                }
            }catch (Exception e){
                return new MessageVO(BaseErrorCodeEnum.PARAM_ERR.getErrorCode(), "参数格式错误");
            }

            iPropertyHouseHoldInfoServiceClient.removeUnPassedUser(removeDTOList, projectId);
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode());
        }catch (Exception e){
            throw new DataAccessException("【】删除审批未通过的用户失败", e);
        }
    }



    /**
     * <desc>
     * 上传图片文件
     * <desc/>
     *
     * @param bytes     图片二进制
     * @param imageType 图片类型
     * @return
     * @author Qiang.S
     * @createDate 2018-05-18
     */
    private String uploadImageFile(byte[] bytes, String imageType, FileCatalogEnum fileCatalog) {
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
        UploadFileUtil.UploadFile uploadFileUtil = new UploadFileUtil().new UploadFile(
                FILE_FTP_HOST,
                FILE_FTP_USERNAME,
                FILE_FTP_PASSWORD,
                FILE_FTP_PORT,
                byteArrayInputStream,
                imageType,
                FILE_ACCESS_URL,
                fileCatalog.getType()
        );
        try {
            //LOG.info("正在上传图片");
            Map<String, Object> resultMap = UploadFileUtil.uploadFile(uploadFileUtil);
            //LOG.info("图片上传完毕");
            String returnCode = resultMap.get("returnCode").toString();
            if ("true".equals(returnCode)) {
                String fileUrl = resultMap.get("accessPath").toString();
                return fileUrl;
            } else {
                LOG.info(String.format("图片上传失败，returnCode: %s", returnCode));
                return null;
            }
        } catch (IOException e) {
            LOG.info("UploadFileUtil.uploadFile失败", e);
            return null;
        }
    }

}